# Source: src/js/views/metadata/EMLGeoCoverageView.js

    /* global define */
    define(['underscore', 'jquery', 'backbone',
        'models/metadata/eml211/EMLGeoCoverage',
        'text!templates/metadata/EMLGeoCoverage.html'],
        function (_, $, Backbone, EMLGeoCoverage, EMLGeoCoverageTemplate) {

            /**
            * @class EMlGeoCoverageView
            * @classdesc  The EMLGeoCoverage renders the content of an EMLGeoCoverage model
            * @classcategory Views/Metadata
            * @extends Backbone.View
            */
            var EMLGeoCoverageView = Backbone.View.extend(
                /** @lends EMLGeoCoverageView.prototype */{

                type: "EMLGeoCoverageView",

                tagName: "div",

                className: "row-fluid eml-geocoverage",

                attributes: {
                    "data-category": "geoCoverage"
                },

                editTemplate: _.template(EMLGeoCoverageTemplate),

                initialize: function (options) {
                    if (!options)
                        var options = {};

                    this.isNew = options.isNew || (options.model ? false : true);
                    this.model = options.model || new EMLGeoCoverage();
                    this.edit = options.edit || false;
                },

                events: {
                    "change": "updateModel",
                    "mouseover .remove": "toggleRemoveClass",
                    "mouseout  .remove": "toggleRemoveClass"
                },

                render: function (e) {
                    //Save the view and model on the element
                    this.$el.data({
                        model: this.model,
                        view: this
                    });

                    this.$el.html(this.editTemplate({
                        edit: this.edit,
                        model: this.model.toJSON()
                    }));

                    if (this.isNew) {
                        this.$el.addClass("new");
                    }

                    return this;
                },

                /**
                 * Updates the model.
                 * If this is called from the user switching between latitude and longitude boxes,
                 * we check to see if the input was valid and display any errors if we need to.
                 *
                 * @param e The event
                 */
                updateModel: function (e) {
                    if (!e) return false;

                    e.preventDefault();

                    //Get the attribute and value
                    var element = $(e.target),
                        value = element.val(),
                        attribute = element.attr("data-attribute");

                    //Get the attribute that was changed
                    if (!attribute) return false;

                    var emlModel = this.model.getParentEML();
                    if(emlModel){
                      value = emlModel.cleanXMLText(value);
                    }

                    //Are the NW and SE points the same? i.e. is this a single point and not a box?
                    var isSinglePoint = (this.model.get("north") != null && this.model.get("north") == this.model.get("south")) &&
                        (this.model.get("west") != null && this.model.get("west") == this.model.get("east")),
                        hasEmptyInputs = this.$("[data-attribute='north']").val() == "" ||
                            this.$("[data-attribute='south']").val() == "" ||
                            this.$("[data-attribute='west']").val() == "" ||
                            this.$("[data-attribute='east']").val() == "";

                    //Update the model
                    if (value == "")
                        this.model.set(attribute, null);
                    else
                        this.model.set(attribute, value);

                    //If the NW and SE points are the same point...
                    if (isSinglePoint && hasEmptyInputs) {
                        /* If the user updates one of the empty number inputs, then we can assume they do not
                        *   want a single point and are attempting to enter a second point. So we should empty the
                        *   value from the model for the corresponding coordinate
                        *   For example, if the UI shows a lat,long pair of NW: [10] [30] SE: [ ] [ ] then the model
                        *     values would be N: 10, W: 30, S: 10, E: 30
                        *     if the user updates that to:   NW: [10] [30] SE: [5] [ ]
                        *     then we want to remove the "east" value of "30", so the model would be: N: 10, W: 30, S: 5, E: null
                        */
                        if (attribute == "north" && this.$("[data-attribute='west']").val() == "")
                            this.model.set("west", null);
                        else if (attribute == "south" && this.$("[data-attribute='east']").val() == "")
                            this.model.set("east", null);
                        else if (attribute == "east" && this.$("[data-attribute='south']").val() == "")
                            this.model.set("south", null);
                        else if (attribute == "west" && this.$("[data-attribute='north']").val() == "")
                            this.model.set("north", null);

                        /*
                         * If the user removes one of the latitude or longitude values, reset the opposite point
                         */
                        else if (((attribute == "north" && this.model.get("north") == null) ||
                            (attribute == "west" && this.model.get("west") == null)) &&
                            (this.$("[data-attribute='south']").val() == "" &&
                                this.$("[data-attribute='east']").val() == "")) {
                            this.model.set("south", null);
                            this.model.set("east", null);
                        } else if (((attribute == "south" && this.model.get("south") == null) ||
                            (attribute == "east" && this.model.get("east") == null)) &&
                            (this.$("[data-attribute='north']").val() == "" && this.$("[data-attribute='west']").val() == "")) {
                            this.model.set("north", null);
                            this.model.set("west", null);
                        }
    	        		/* Otherwise, if the non-empty number inputs are updated,
    	        		 *  we simply update the corresponding value in the other point
    	        		 */
                        else if (attribute == "north" && this.model.get("north") != null)
                            this.model.set("south", value);
                        else if (attribute == "south" && this.model.get("south") != null)
                            this.model.set("north", value);
                        else if (attribute == "west" && this.model.get("west") != null)
                            this.model.set("east", value);
                        else if (attribute == "east" && this.model.get("east") != null)
                            this.model.set("west", value);
                    }
                    else {

                        //Find out if we are missing a complete NW or SE point
                        var isMissingNWPoint = (this.model.get("north") == null && this.model.get("west") == null),
                            isMissingSEPoint = (this.model.get("south") == null && this.model.get("east") == null);

                        // If there is a full NW point but no SE point, we can assume the user wants a single point and
                        //  so we will copy the NW values to the SE
                        if (this.model.get("north") != null && this.model.get("west") != null && isMissingSEPoint) {
                            this.model.set("south", this.model.get("north"));
                            this.model.set("east", this.model.get("west"));
                        }
                        // Same for when there is a SE point but no NW point
                        else if (this.model.get("south") != null && this.model.get("east") != null && isMissingNWPoint) {
                            this.model.set("north", this.model.get("south"));
                            this.model.set("west", this.model.get("east"));
                        }
                    }

                    // Validate the coordinate boxes
                    //this.validateCoordinates(e);

                    //If this model is part of the EML inside the root data package, mark the package as changed
                    if (this.model.get("parentModel")) {
                        if (this.model.get("parentModel").type == "EML" && _.contains(MetacatUI.rootDataPackage.models, this.model.get("parentModel"))) {
                            MetacatUI.rootDataPackage.packageModel.set("changed", true);
                        }
                    }

                    this.validate();
                },

                /**
                 * Checks to see if any error messages need to be removed. If not, then it performs validation
                 * across the row and displays any errors. This id called when the user clicks out of an edit box
                 * on to the page.
                 *
                 * @param e The event
                 * @param options
                 */
                validate: function (e, options) {

                	//Query for the EMlGeoCoverageView element that the user is actively interacting with
                    var activeGeoCovEl = $(document.activeElement).parents(".eml-geocoverage");

                    //If the user is not actively in this view, then exit
                    if (activeGeoCovEl.length && activeGeoCovEl[0] == this.el)
                        return;

                    //If the model is valid, then remove error styling and exit
                    if( this.model.isValid() ) {
                    	this.$(".error").removeClass("error");
                    	this.$el.removeClass("error");
                    	this.$(".notification").empty();
                    	this.model.trigger("valid");

                        return;
                    }
                    else{

                    	this.showValidation();

                    }

                },

                /*
                 * Resets the error messaging and displays the current error messages for this model
                 * This function is used by the EML211EditorView during the package validation process
                 */
                showValidation: function(){
                	this.$(".error").removeClass("error");
                	this.$el.removeClass("error");
                	this.$(".notification").empty();

                	var errorMessages = "";

                	for( field in this.model.validationError ){
                		this.$("[data-attribute='" + field + "']").addClass("error");

                		errorMessages += this.model.validationError[field] + " ";
                	}

            		this.$(".notification").text(errorMessages).addClass("error");
                },

                /**
                 * Highlight what will be removed when the remove icon is hovered over
                 *
                 */
                toggleRemoveClass: function () {
                    this.$el.toggleClass("remove-preview");
                },

                /**
                 * Unmarks this view as new
                 *
                 */
                notNew: function () {
                    this.$el.removeClass("new");
                    this.isNew = false;
                }
            });

            return EMLGeoCoverageView;
        });