/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(['require',
    'backbone',
    'hbs!tmpl/search/QueryBuilder_tmpl',
    'utils/Utils',
    'utils/CommonViewFunction',
    'utils/Enums',
    'query-builder',
    'daterangepicker'
], function(require, Backbone, QueryBuilder_Tmpl, Utils, CommonViewFunction, Enums) {

    var QueryBuilderView = Backbone.Marionette.LayoutView.extend(
        /** @lends QueryBuilderView */
        {
            _viewName: 'QueryBuilderView',

            template: QueryBuilder_Tmpl,



            /** Layout sub regions */
            regions: {},


            /** ui selector cache */
            ui: {
                "builder": "#builder"
            },
            /** ui events hash */
            events: function() {
                var events = {};
                return events;
            },
            /**
             * intialize a new QueryBuilderView Layout
             * @constructs
             */
            initialize: function(options) {
                _.extend(this, _.pick(options, 'attrObj', 'value', 'typeHeaders', 'entityDefCollection', 'enumDefCollection', 'tag', 'searchTableFilters', 'systemAttrArr'));
                this.attrObj = _.sortBy(this.attrObj, 'name');
                this.systemAttrArr = _.sortBy(this.systemAttrArr, 'name');
                this.filterType = this.tag ? 'tagFilters' : 'entityFilters';
            },
            bindEvents: function() {},
            getOperator: function(type) {
                var obj = {
                    operators: null
                }
                if (type === "string") {
                    obj.operators = ['=', '!=', 'contains', 'begins_with', 'ends_with'];
                }
                if (type === "date" || type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double") {
                    obj.operators = ['=', '!=', '>', '<', '>=', '<='];
                }
                if (type === "enum" || type === "boolean") {
                    obj.operators = ['=', '!='];
                }
                if (obj.operators) {
                    obj.operators = obj.operators.concat(['is_null', 'not_null']);
                }
                return obj;
            },
            isPrimitive: function(type) {
                if (type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double" || type === "string" || type === "boolean" || type === "date") {
                    return true;
                }
                return false;
            },
            getObjDef: function(attrObj, rules, isGroup, groupType, isSystemAttr) {
                if (attrObj.name === "__classificationsText" || attrObj.name === "__historicalGuids") {
                    return;
                }
                var obj = {
                    id: attrObj.name,
                    label: (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (" + attrObj.typeName + ")",
                    type: _.escape(attrObj.typeName)
                };
                if (isGroup) {
                    obj.optgroup = groupType;
                }
                if (isSystemAttr && attrObj.name === "__isIncomplete" || isSystemAttr && attrObj.name === "IsIncomplete") {
                    obj.type = "boolean";
                    obj.label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (boolean)";
                    obj['input'] = 'select';
                    obj['values'] = [{ 1: 'true' }, { 0: 'false' }];
                    obj.operators = ['=', '!=', 'is_null', 'not_null'];
                    return obj;
                }
                if (isSystemAttr && attrObj.name === "Status" || isSystemAttr && attrObj.name === "__state") {
                    obj.label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (enum)";
                    obj['input'] = 'select';
                    obj['values'] = ['ACTIVE', 'DELETED'];
                    obj.operators = ['=', '!='];
                    return obj;
                }

                if (obj.type === "date") {
                    obj['plugin'] = 'daterangepicker';
                    obj['plugin_config'] = {
                        "singleDatePicker": true,
                        "showDropdowns": true,
                        "timePicker": true,
                        locale: {
                            format: 'MM/DD/YYYY h:mm A'
                        }
                    };
                    if (rules) {
                        var valueObj = _.find(rules, { id: obj.id });
                        if (valueObj) {
                            obj.plugin_config["startDate"] = valueObj.value;
                        }
                    }
                    _.extend(obj, this.getOperator(obj.type));
                    return obj;
                }
                if (this.isPrimitive(obj.type)) {
                    if (obj.type === "boolean") {
                        obj['input'] = 'select';
                        obj['values'] = ['true', 'false'];
                    }
                    _.extend(obj, this.getOperator(obj.type));
                    if (_.has(Enums.regex.RANGE_CHECK, obj.type)) {
                        obj.validation = {
                            min: Enums.regex.RANGE_CHECK[obj.type].min,
                            max: Enums.regex.RANGE_CHECK[obj.type].max
                        };
                        if (obj.type === "double" || obj.type === "float") {
                            obj.type = "double";
                        } else if (obj.type === "int" || obj.type === "byte" || obj.type === "short" || obj.type === "long") {
                            obj.type = "integer"
                        }
                    }
                    return obj;
                }
                var enumObj = this.enumDefCollection.fullCollection.find({ name: obj.type });
                if (enumObj) {
                    obj.type = "string";
                    obj['input'] = 'select';
                    var value = [];
                    _.each(enumObj.get('elementDefs'), function(o) {
                        value.push(o.value)
                    })
                    obj['values'] = value;
                    _.extend(obj, this.getOperator('enum'));
                    return obj;
                }
            },
            onRender: function() {
                var that = this,
                    filters = [],
                    isGroupView = false,
                    placeHolder = '--Select Attribute--';
                if (this.attrObj.length > 0 && this.systemAttrArr.length > 0) {
                    isGroupView = true;
                } else if (this.attrObj.length === 0 || this.systemAttrArr.length === 0) {
                    isGroupView = false;
                }
                if (this.attrObj.length === 0) {
                    placeHolder = '--Select System Attribute--';
                }
                if (this.value) {
                    var rules_widgets = CommonViewFunction.attributeFilter.extractUrl({ "value": this.searchTableFilters[this.filterType][(this.tag ? this.value.tag : this.value.type)], "formatDate": true });
                }
                _.each(this.attrObj, function(obj) {
                    var type = that.tag ? 'Classification' : 'Entity';
                    var returnObj = that.getObjDef(obj, rules_widgets, isGroupView, 'Select ' + type + ' Attribute');
                    if (returnObj) {
                        filters.push(returnObj);
                    }
                });
                _.each(this.systemAttrArr, function(obj) {
                    var returnObj = that.getObjDef(obj, rules_widgets, isGroupView, 'Select System Attribute', true);
                    if (returnObj) {
                        filters.push(returnObj);
                    }
                });
                filters = _.uniq(filters, 'id');
                if (filters && !_.isEmpty(filters)) {
                    this.ui.builder.queryBuilder({
                        plugins: ['bt-tooltip-errors'],
                        filters: filters,
                        select_placeholder: placeHolder,
                        allow_empty: true,
                        conditions: ['AND', 'OR'],
                        allow_groups: true,
                        allow_empty: true,
                        operators: [
                            { type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] },
                            { type: '!=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] },
                            { type: '>', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] },
                            { type: '<', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] },
                            { type: '>=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] },
                            { type: '<=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] },
                            { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] },
                            { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
                            { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
                            { type: 'is_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] },
                            { type: 'not_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }
                        ],
                        lang: {
                            add_rule: 'Add filter',
                            add_group: 'Add filter group',
                            operators: {
                                not_null: 'is not null'
                            }
                        },
                        icons: {
                            add_rule: 'fa fa-plus',
                            remove_rule: 'fa fa-times',
                            error: 'fa fa-exclamation-triangle'
                        },
                        rules: rules_widgets
                    });
                    this.$('.rules-group-header .btn-group.pull-right.group-actions').toggleClass('pull-left');
                } else {
                    this.ui.builder.html('<h4>No Attributes are available !</h4>')
                }
            }
        });
    return QueryBuilderView;
});