Source: src/js/models/metadata/eml211/EMLAnnotation.js

define(["jquery", "underscore", "backbone"], function ($, _, Backbone) {
  /**
   * @class EMLAnnotation
   * @classdesc Stores EML SemanticAnnotation elements.
   * @classcategory Models/Metadata/EML211
   * @see https://eml.ecoinformatics.org/eml-2.2.0/eml-semantics.xsd
   * @extends Backbone.Model
   */
  var EMLAnnotation = Backbone.Model.extend(
    /** @lends EMLAnnotation.prototype */ {
      type: "EMLAnnotation",

      defaults: function () {
        return {
          isNew: true,
          propertyLabel: null,
          propertyURI: null,
          valueLabel: null,
          valueURI: null,
          objectDOM: null,
          objectXML: null,
        };
      },

      initialize: function (attributes, opions) {
        this.on("change", this.trickleUpChange);
      },

      parse: function (attributes, options) {
        // If parsing, this is an existing annotation so it's not isNew
        attributes.isNew = false;

        var propertyURI = $(attributes.objectDOM).find("propertyuri");
        var valueURI = $(attributes.objectDOM).find("valueuri");

        if (propertyURI.length !== 1 || valueURI.length !== 1) {
          return;
        }

        attributes.propertyURI = $(propertyURI).text().trim();

        attributes.valueURI = $(valueURI).text().trim();

        var propertyLabel = $(propertyURI).attr("label");
        var valueLabel = $(valueURI).attr("label");

        if (!propertyLabel || !valueLabel) {
          return;
        }

        attributes.propertyLabel = propertyLabel.trim();
        attributes.valueLabel = valueLabel.trim();

        return attributes;
      },

      validate: function () {
        var errors = [];

        if (this.isEmpty()) {
          this.trigger("valid");

          return;
        }

        var propertyURI = this.get("propertyURI");

        if (!propertyURI || propertyURI.length <= 0) {
          errors.push({
            category: "propertyURI",
            message: "Property URI must be set.",
          });
        } else if (propertyURI.match(/http[s]?:\/\/.+/) === null) {
          errors.push({
            category: "propertyURI",
            message: "Property URI should be an HTTP(S) URI.",
          });
        }

        var propertyLabel = this.get("propertyLabel");

        if (!propertyLabel || propertyLabel.length <= 0) {
          errors.push({
            category: "propertyLabel",
            message: "Property Label must be set.",
          });
        }

        var valueURI = this.get("valueURI");

        if (!valueURI || valueURI.length <= 0) {
          errors.push({
            category: "valueURI",
            message: "Value URI must be set.",
          });
        } else if (valueURI.match(/http[s]?:\/\/.+/) === null) {
          errors.push({
            category: "valueURI",
            message: "Value URI should be an HTTP(S) URI.",
          });
        }

        var valueLabel = this.get("valueLabel");

        if (!valueLabel || valueLabel.length <= 0) {
          errors.push({
            category: "valueLabel",
            message: "Value Label must be set.",
          });
        }

        if (errors.length === 0) {
          this.trigger("valid");

          return;
        }

        return errors;
      },

      updateDOM: function (objectDOM) {
        objectDOM = document.createElement("annotation");

        if (this.get("propertyURI")) {
          var propertyURIEl = document.createElement("propertyuri");
          $(propertyURIEl).html(this.get("propertyURI"));

          if (this.get("propertyLabel")) {
            $(propertyURIEl).attr("label", this.get("propertyLabel"));
          }

          $(objectDOM).append(propertyURIEl);
        }

        if (this.get("valueURI")) {
          var valueURIEl = document.createElement("valueuri");
          $(valueURIEl).html(this.get("valueURI"));

          if (this.get("valueLabel")) {
            $(valueURIEl).attr("label", this.get("valueLabel"));
          }

          $(objectDOM).append(valueURIEl);
        }

        return objectDOM;
      },

      formatXML: function (xmlString) {
        return DataONEObject.prototype.formatXML.call(this, xmlString);
      },

      /**
       * isEmpty
       *
       * Check whether the model's properties are all empty for the purpose
       * of skipping the model during serialization to avoid invalid EML
       * documents.
       *
       * @return {boolean} - Returns true if all child elements have no
       * content
       */
      isEmpty: function () {
        return (
          (typeof this.get("propertyLabel") !== "string" ||
            this.get("propertyLabel").length <= 0) &&
          (typeof this.get("propertyURI") !== "string" ||
            this.get("propertyURI").length <= 0) &&
          (typeof this.get("valueLabel") !== "string" ||
            this.get("valueLabel").length <= 0) &&
          (typeof this.get("valueURI") !== "string" ||
            this.get("valueURI").length <= 0)
        );
      },

      /* Let the top level package know of attribute changes from this object */
      trickleUpChange: function () {
        MetacatUI.rootDataPackage.packageModel.set("changed", true);
      },
    },
  );

  return EMLAnnotation;
});