# Source: src/js/models/maps/VectorFilter.js

    'use strict';

    define(
      [
        'jquery',
        'underscore',
        'backbone'
      ],
      function (
        $,
        _,
        Backbone
      ) {
        /**
         * @classdesc A VectorFilter Model represents one condition used to show or hide
         * specific features of a vector layer on a map. The filter defines rules used to show
         * features conditionally based on properties of the feature. For example, it could
         * specify hiding all vectors for an asset that have an area greater than 10 km2.
         * @classcategory Models/Maps
         * @class VectorFilter
         * @name VectorFilter
         * @extends Backbone.Model
         * @since 2.18.0
         * @constructor
        */
        var VectorFilter = Backbone.Model.extend(
          /** @lends VectorFilter.prototype */ {

            /**
             * The name of this type of model
             * @type {string}
            */
            type: 'VectorFilter',

            /**
             * A VectorFilterConfig specifies conditions under which specific features of a
             * vector layer on a map should be visible. The filter defines rules used to show
             * features conditionally based on properties of the feature. For example, it
             * could specify hiding all vectors for an asset that have an area greater than
             * 10km2. This configuration is passed to the {@link VectorFilter} model.
             * @typedef {Object} VectorFilterConfig
             * @name MapConfig#VectorFilterConfig
             * @property {('categorical'|'numeric')} filterType If categorical, then a feature
             * will be visible when its property value exactly matches one of those listed in
             * the values attribute. If numeric, then a feature will be visible when its
             * property value is between the min and max.
             * @property {string} property The property (attribute) of the {@link MapAsset}
             * feature to filter on.
             * @property {(string[]|number[])} values Only used for categorical filters. If
             * the property matches one of the values listed, the feature will be displayed.
             * If the filter type is categorical and no values are set, then features will not
             * be filtered on this property.
             * @property {number} max Only used for numeric filters. The property's value must
             * be less than the value set here for the feature to be visible. If the filter
             * type is numeric, and max is set, then the max is infinite.
             * @property {number} min Only used for numeric filters. The property's value must
             * be greater than the value set here for the feature to be visible. If the filter
             * type is numeric, and min is set, then the min is minus infinity.
             *
             * @example
             * // Only show vectors with an 'area' property set to less than 10
             * {
             *   filterType: 'numeric'
             *   property: 'area'
             *   max: 10
             * }
             *
             * @example
             * // Show only features that have the 'boreal' or 'tropical' property set on their 'forestType' attribute
             * {
             *   filterType: 'categorical'
             *   property: 'forestType'
             *   values: ['boreal', 'tropical']
             * }
             */

            /**
             * Default attributes for VectorFilter models
             * @name VectorFilter#defaults
             * @type {Object}
             * @property {('categorical'|'numeric')} [filterType='categorical'] If
             * categorical, then a feature will be visible when its property value exactly
             * matches one of those listed in the values attribute. If numerical, then a
             * feature will be visible when its property value is between the min and max.
             * @property {string} property The property (attribute) of the feature to filter
             * on.
             * @property {(string[]|number[])} values Only used for categorical filters. If
             * the property matches one of the values listed, the feature will be displayed.
             * If the filter type is categorical and no values are set, then features will not
             * be filtered on this property.
             * @property {number} max Only used for numeric filters. The property's value must
             * be less than the value set here for the feature to be visible. If the filter
             * type is numeric, and max is set, then the max is infinite.
             * @property {number} min Only used for numeric filters. The property's value must
             * be greater than the value set here for the feature to be visible. If the filter
             * type is numeric, and min is set, then the min is minus infinity.
             *
            */
            defaults: function () {
              return {
                filterType: 'categorical',
                property: null,
                values: [],
                max: null,
                min: null
              }
            },

            /**
             * This function checks if a feature is visible based on the filter's rules.
             * @param {Object} properties The properties of the feature to be filtered. (See
             * the 'properties' attribute of {@link Feature#defaults}.)
             * @returns {boolean} Returns true if the feature properties pass this filter
             */
            featureIsVisible: function (properties) {
              try {
                if (!properties) {
                  properties = {};
                }
                var visible = true;
                if (this.get('filterType') === 'categorical') {
                  var values = this.get('values');
                  if (values.length > 0) {
                    visible = _.contains(values, properties[this.get('property')]);
                  }
                } else if (this.get('filterType') === 'numeric') {
                  var max = this.get('max');
                  var min = this.get('min');
                  if (max !== null) {
                    visible = properties[this.get('property')] < max;
                  }
                  if (min !== null) {
                    visible = properties[this.get('property')] > min && visible;
                  }
                }
                return visible;
              }
              catch (error) {
                console.log(
                  'There was an error checking feature visibility in a VectorFilter' +
                  '. Error details: ' + error
                );
              }
            },

            // /**
            //  * Executed when a new VectorFilter model is created.
            //  * @param {Object} [attributes] The initial values of the attributes, which will
            //  * be set on the model.
            //  * @param {Object} [options] Options for the initialize function.
            //  */
            // initialize: function (attributes, options) {
            //   try {

            //   }
            //   catch (error) {
            //     console.log(
            //       'There was an error initializing a VectorFilter model' +
            //       '. Error details: ' + error
            //     );
            //   }
            // },

            // /**
            //  * Parses the given input into a JSON object to be set on the model.
            //  *
            //  * @param {TODO} input - The raw response object
            //  * @return {TODO} - The JSON object of all the VectorFilter attributes
            //  */
            // parse: function (input) {

            //   try {

            //     var modelJSON = {};

            //     return modelJSON

            //   }
            //   catch (error) {
            //     console.log(
            //       'There was an error parsing a VectorFilter model' +
            //       '. Error details: ' + error
            //     );
            //   }

            // },

            // /**
            //  * Overrides the default Backbone.Model.validate.function() to check if this if
            //  * the values set on this model are valid.
            //  *
            //  * @param {Object} [attrs] - A literal object of model attributes to validate.
            //  * @param {Object} [options] - A literal object of options for this validation
            //  * process
            //  *
            //  * @return {Object} - Returns a literal object with the invalid attributes and
            //  * their corresponding error message, if there are any. If there are no errors,
            //  * returns nothing.
            //  */
            // validate: function (attrs, options) {
            //   try {

            //   }
            //   catch (error) {
            //     console.log(
            //       'There was an error validating a VectorFilter model' +
            //       '. Error details: ' + error
            //     );
            //   }
            // },

            // /**
            //  * Creates a string using the values set on this model's attributes.
            //  * @return {string} The VectorFilter string
            //  */
            // serialize: function () {
            //   try {
            //     var serializedVectorFilter = '';

            //     return serializedVectorFilter;
            //   }
            //   catch (error) {
            //     console.log(
            //       'There was an error serializing a VectorFilter model' +
            //       '. Error details: ' + error
            //     );
            //   }
            // },

          });

        return VectorFilter;

      }
    );