define(["jquery", "underscore", "backbone", "models/metadata/eml211/EMLEntity"],
    function($, _, Backbone, EMLEntity) {

        /**
        * @class EMLOtherEntity
         * @classdesc EMLOtherEntity represents a generic data entity, corresponding
         * with the EML otherEntity module.
         * @classcategory Models/Metadata/EML211
         * @see https://eml.ecoinformatics.org/schema/eml-dataset_xsd.html#DatasetType_otherEntity
         * @extends EMLEntity
         */
        var EMLOtherEntity = EMLEntity.extend(
          /** @lends EMLOtherEntity.prototype */{

        	//The class name for this model
        	type: "EMLOtherEntity",

            /* Attributes of any entity */
            defaults: function(){
	            return	_.extend({

		                /* Attributes from EML */
                    entityType: "data entity",

		                /* Attributes not from EML */
		                nodeOrder: [ // The order of the top level XML element nodes
		                    "alternateIdentifier",
		                    "entityName",
		                    "entityDescription",
		                    "physical",
		                    "coverage",
		                    "methods",
		                    "additionalInfo",
		                    "attributeList",
		                    "constraint",
		                    "entityType"
		                ],

	            	}, EMLEntity.prototype.defaults());
            },

            /*
             * The map of lower case to camel case node names
             * needed to deal with parsing issues with $.parseHTML().
             * Use this until we can figure out issues with $.parseXML().
             */
            nodeNameMap: _.extend({
                "entitytype": "entityType"

            }, EMLEntity.prototype.nodeNameMap),

            /* Initialize an EMLOtherEntity object */
            initialize: function(attributes) {

                // if options.parse = true, Backbone will call parse()

                // Call super() first
                this.constructor.__super__.initialize.apply(this, [attributes]);

                // EMLOtherEntity-specific work
                this.set("type", "otherEntity", {silent: true});

                // Register change events
                this.on( "change:entityType", EMLEntity.trickleUpChange);

            },

            /*
             * Parse the incoming other entity's XML elements
             */
            parse: function(attributes, options) {

                var attributes = attributes || {};

                // Call super() first
                attributes = this.constructor.__super__.parse.apply(this, [attributes, options]);

                // EMLOtherEntity-specific work
                var objectXML  = attributes.objectXML; // The otherEntity XML fragment
                var objectDOM; // The W3C DOM of the object XML fragment
                var $objectDOM; // The JQuery object of the XML fragment

                // Use the updated objectDOM if we have it
                if ( attributes.objectDOM ) {
                    $objectDOM = $(attributes.objectDOM);
                } else {
                    // Hmm, oddly not there, start from scratch =/
                    $objectDOM = $(objectXML);
                }

                // Add the entityType
                attributes.entityType = $objectDOM.children("entitytype").text();

                return attributes;
            },

            /* Copy the original XML and update fields in a DOM object */
            updateDOM: function(objectDOM) {
                var nodeToInsertAfter;
                var type = this.get("type") || "otherEntity";
                if ( ! objectDOM ) {
                    objectDOM = this.get("objectDOM");
                }
                var objectXML = this.get("objectXML");

                // If present, use the cached DOM
                if ( objectDOM ) {
                    objectDOM = objectDOM.cloneNode(true);

                // otherwise, use the cached XML
                } else if ( objectXML ){
                    objectDOM = $(objectXML)[0].cloneNode(true);

                // This is new, create it
                } else {
                    objectDOM = document.createElement(type);

                }

                // Now call the superclass
                objectDOM = this.constructor.__super__.updateDOM.apply(this, [objectDOM]);

                // And then update the EMLOtherEntity-specific fields
                // Update the entityName
                if ( this.get("entityType") ) {
                    if ( $(objectDOM).find("entityType").length ) {
                        $(objectDOM).find("entityType").text(this.get("entityType"));

                    } else {
                        nodeToInsertAfter = this.getEMLPosition(objectDOM, "entityType");

                        if ( ! nodeToInsertAfter ) {
                            $(objectDOM).append($(document.createElement("entitytype"))
                                .text(this.get("entityType"))[0]);
                        } else {
                            $(nodeToInsertAfter).after($(document.createElement("entitytype"))
                                .text(this.get("entityType"))[0]);
                        }
                    }
                }

                return objectDOM;
            },

            /*
            * Climbs up the model heirarchy until it finds the EML model
            *
            * @return {EML211 or false} - Returns the EML 211 Model or false if not found
            */
            getParentEML: function(){
              var emlModel = this.get("parentModel"),
                  tries = 0;

              while (emlModel.type !== "EML" && tries < 6){
                emlModel = emlModel.get("parentModel");
                tries++;
              }

              if( emlModel && emlModel.type == "EML")
                return emlModel;
              else
                return false;

            },

            /* Serialize the EML DOM to XML */
            serialize: function() {

                var xmlString = "";

                // Update the superclass fields in the objectDOM first
                var objectDOM = this.constructor.__super__.updateDOM.apply(this, []);

                // Then update the subclass fields in the objectDOM
                // TODO


                this.set("objectXML", xmlString);

                return xmlString;
            }

        });

        return EMLOtherEntity;
    }
);
