text: "use strict";
  
  /*global require*/
  var clone = require("terriajs-cesium/Source/Core/clone").default;
  var defined = require("terriajs-cesium/Source/Core/defined").default;
  var RuntimeError = require("terriajs-cesium/Source/Core/RuntimeError").default;
  var when = require("terriajs-cesium/Source/ThirdParty/when").default;
  var GeoJsonCatalogItem = require("./GeoJsonCatalogItem");
  var CatalogItem = require("./CatalogItem");
  var inherit = require("../Core/inherit");
  const loadXML = require("../Core/loadXML");
  var Metadata = require("./Metadata");
  var proxyCatalogItemUrl = require("./proxyCatalogItemUrl");
  var geoRssConvertor = require("../Map/geoRssConvertor");
  var geoRss2Convertor = geoRssConvertor.geoRss2ToGeoJson;
  var geoRssAtomConvertor = geoRssConvertor.geoRssAtomToGeoJson;
  
  /**
   * A {@link CatalogItem} representing GeoRSS data.
   *
   * @alias GeoRssCatalogItem
   * @constructor
   * @extends CatalogItem
   *
   * @param {Terria} terria The Terria instance.
   * @param {String} [url] The URL from which to retrieve the CZML data.
   */
  function GeoRssCatalogItem(terria) {
    CatalogItem.call(this, terria);
  
    this._geoJsonItem = undefined;
  }
  
  inherit(CatalogItem, GeoRssCatalogItem);
  
  Object.defineProperties(GeoRssCatalogItem.prototype, {
    /**
     * Returns true if we can zoom to this item. Depends on observable properties, and so updates once loaded.
     * @memberOf GeoRssCatalogItem.prototype
     * @type {Boolean}
     */
    canZoomTo: {
      get: function() {
        return true;
      }
    },
  
    /**
     * Gets the type of data member represented by this instance.
     * @memberOf GeoRssCatalogItem.prototype
     * @type {String}
     */
    type: {
      get: function() {
        return "georss";
      }
    },
  
    /**
     * Gets a human-readable name for this type of data source, 'GeoRSS'.
     * @memberOf GeoRssCatalogItem.prototype
     * @type {String}
     */
    typeName: {
      get: function() {
        return "GeoRSS";
      }
    },
  
    /**
     * Gets the metadata associated with this data source and the server that provided it, if applicable.
     * @memberOf GeoRssCatalogItem.prototype
     * @type {Metadata}
     */
    metadata: {
      get: function() {
        var result = new Metadata();
        result.isLoading = false;
        result.dataSourceErrorMessage =
          "This data source does not have any details available.";
        result.serviceErrorMessage =
          "This service does not have any details available.";
        return result;
      }
    },
  
    /**
     * Gets the set of functions used to update individual properties in {@link CatalogMember#updateFromJson}.
     * When a property name in the returned object literal matches the name of a property on this instance, the value
     * will be called as a function and passed a reference to this instance, a reference to the source JSON object
     * literal, and the name of the property.
     * @memberOf GeoRssCatalogItem.prototype
     * @type {Object}
     */
    updaters: {
      get: function() {
        return GeoRssCatalogItem.defaultUpdaters;
      }
    },
  
    /**
     * Gets the set of functions used to serialize individual properties in {@link CatalogMember#serializeToJson}.
     * When a property name on the model matches the name of a property in the serializers object literal,
     * the value will be called as a function and passed a reference to the model, a reference to the destination
     * JSON object literal, and the name of the property.
     * @memberOf GeoRssCatalogItem.prototype
     * @type {Object}
     */
    serializers: {
      get: function() {
        return GeoRssCatalogItem.defaultSerializers;
      }
    },
  
    /**
     * Gets the data source associated with this catalog item.
     * @memberOf GeoRssCatalogItem.prototype
     * @type {DataSource}
     */
    dataSource: {
      get: function() {
        return defined(this._geoJsonItem)
          ? this._geoJsonItem.dataSource
          : undefined;
      }
    }
  });
  
  GeoRssCatalogItem.defaultUpdaters = clone(CatalogItem.defaultUpdaters);
  Object.freeze(GeoRssCatalogItem.defaultUpdaters);
  
  GeoRssCatalogItem.defaultSerializers = clone(CatalogItem.defaultSerializers);
  
  GeoRssCatalogItem.prototype._getValuesThatInfluenceLoad = function() {
    return [this.url];
  };
  
  GeoRssCatalogItem.prototype._load = function() {
    this._geoJsonItem = new GeoJsonCatalogItem(this.terria);
    this._geoJsonItem.data = loadGeoRss(this);
    this._geoJsonItem.name = this.name;
    var that = this;
  
    return this._geoJsonItem.load().then(function() {
      if (!defined(that.rectangle)) {
        that.rectangle = that._geoJsonItem.rectangle;
      }
    });
  };
  
  GeoRssCatalogItem.prototype._enable = function() {
    if (defined(this._geoJsonItem)) {
      this._geoJsonItem._enable();
    }
  };
  
  GeoRssCatalogItem.prototype._disable = function() {
    if (defined(this._geoJsonItem)) {
      this._geoJsonItem._disable();
    }
  };
  
  GeoRssCatalogItem.prototype._show = function() {
    if (defined(this._geoJsonItem)) {
      this._geoJsonItem._show();
    }
  };
  
  GeoRssCatalogItem.prototype._hide = function() {
    if (defined(this._geoJsonItem)) {
      this._geoJsonItem._hide();
    }
  };
  
  GeoRssCatalogItem.prototype.showOnSeparateMap = function(globeOrMap) {
    if (defined(this._geoJsonItem)) {
      return this._geoJsonItem.showOnSeparateMap(globeOrMap);
    }
  };
  GeoRssCatalogItem.prototype.zoomTo = function() {
    var that = this;
    return when(this.load(), function() {
      if (defined(that.nowViewingCatalogItem)) {
        return that.nowViewingCatalogItem.zoomTo();
      }
  
      if (defined(that.rectangle)) {
        return CatalogItem.prototype.zoomTo.call(that);
      }
  
      if (!defined(that.dataSource)) {
        return;
      }
  
      return that.terria.currentViewer.zoomTo(that.dataSource);
    });
  };
  
  function loadGeoRss(geoRssItem) {
    return loadXML(proxyCatalogItemUrl(geoRssItem, geoRssItem.url)).then(function(
      xml
    ) {
      if (typeof xml === "string") {
        const parser = new DOMParser();
        xml = parser.parseFromString(xml, "text/xml");
      }
      var documentElement = xml.documentElement;
      var promise;
      if (documentElement.localName === "rss") {
        promise = geoRss2Convertor(xml);
        resolveCatalogMetaData(
          documentElement.getElementsByTagName("channel")[0],
          geoRssItem
        );
      } else if (documentElement.localName === "feed") {
        promise = geoRssAtomConvertor(xml);
        resolveCatalogMetaData(documentElement, geoRssItem);
      } else {
        throw new RuntimeError("document is not valid");
      }
      return promise;
    });
  }
  
  function resolveCatalogMetaData(documentElement, geoRssItem) {
    var childNodes = documentElement.childNodes;
  
    for (
      var childNodeIndex = 0;
      childNodeIndex < childNodes.length;
      ++childNodeIndex
    ) {
      var child = childNodes[childNodeIndex];
      if (
        child.nodeType !== 1 ||
        child.localName === "item" ||
        child.localName === "entry"
      ) {
        continue;
      }
      if (child.localName === "title") {
        geoRssItem.name = child.textContent;
      } else if (child.localName === "description") {
        geoRssItem.description = child.textContent;
      } else if (child.localName === "copyright") {
        geoRssItem.copyrightText = child.copyright;
      } else if (child.localName === "author") {
        var authorNode = child.childNodes;
        var name;
        var email;
        for (
          var authorIndex = 0;
          authorIndex < authorNode.length;
          ++authorIndex
        ) {
          var authorChild = authorNode[authorIndex];
          if (authorChild.nodeType === 1) {
            if (authorChild.localName === "name") {
              name = authorChild.textContent;
            } else if (authorChild.localName === "email") {
              email = authorChild.textContent;
            }
          }
        }
        //TODO: check if this can be dataCustodian or author of the item
        if (name === undefined && email === undefined) {
          geoRssItem.dataCustodian = child.textContent;
        } else {
          geoRssItem.dataCustodian = name + ", " + email;
        }
      }
    }
    if (
      !defined(geoRssItem.name) ||
      geoRssItem.name === geoRssItem.url ||
      geoRssItem.name === "Unnamed Item"
    ) {
      geoRssItem.name = cleanUrl(geoRssItem.url);
    }
  }
  
  function cleanUrl(url) {
    return url.substring(url.lastIndexOf("/") + 1);
  }
  
  module.exports = GeoRssCatalogItem;
  