text: /*
   * Copyright 2003-2006, 2009, 2017, United States Government, as represented by the Administrator of the
   * National Aeronautics and Space Administration. All rights reserved.
   *
   * The NASAWorldWind/WebWorldWind platform is licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  /**
   * @exports WmsLayer
   */
  define([
          '../error/ArgumentError',
          '../geom/Location',
          '../util/Logger',
          '../util/PeriodicTimeSequence',
          '../geom/Sector',
          '../layer/TiledImageLayer',
          '../util/WmsUrlBuilder'
      ],
      function (ArgumentError,
                Location,
                Logger,
                PeriodicTimeSequence,
                Sector,
                TiledImageLayer,
                WmsUrlBuilder) {
          "use strict";
  
          /**
           * Constructs a WMS image layer.
           * @alias WmsLayer
           * @constructor
           * @augments TiledImageLayer
           * @classdesc Displays a WMS image layer.
           * @param {{}} config Specifies configuration information for the layer. Must contain the following
           * properties:
           * <ul>
           *     <li>service: {String} The URL of the WMS server.</li>
           *     <li>layerNames: {String} A comma separated list of the names of the WMS layers to include in this layer.</li>
           *     <li>sector: {Sector} The sector spanned by this layer.</li>
           *     <li>levelZeroDelta: {Location} The level-zero tile delta to use for this layer.</li>
           *     <li>numLevels: {Number} The number of levels to make for this layer.</li>
           *     <li>format: {String} The mime type of the image format to request, e.g., image/png.</li>
           *     <li>size: {Number} The size in pixels of tiles for this layer.</li>
           *     <li>coordinateSystem (optional): {String} The coordinate system to use for this layer, e.g., EPSG:4326.</li>
           *     <li>styleNames (optional): {String} A comma separated list of the styles to include in this layer.</li>
           * </ul>
           * The function [WmsLayer.formLayerConfiguration]{@link WmsLayer#formLayerConfiguration} will create an
           * appropriate configuration object given a {@link WmsLayerCapabilities} object.
           * @param {String} timeString The time parameter passed to the WMS server when imagery is requested. May be
           * null, in which case no time parameter is passed to the server.
           * @throws {ArgumentError} If the specified configuration is null or undefined.
           */
          var WmsLayer = function (config, timeString) {
              if (!config) {
                  throw new ArgumentError(
                      Logger.logMessage(Logger.LEVEL_SEVERE, "WmsLayer", "constructor", "No configuration specified."));
              }
  
              var cachePath = config.service + config.layerNames + config.styleNames;
              if (timeString) {
                  cachePath = cachePath + timeString;
              }
  
              TiledImageLayer.call(this, config.sector, config.levelZeroDelta, config.numLevels, config.format,
                  cachePath, config.size, config.size);
  
              this.displayName = config.title;
              this.pickEnabled = false;
  
              this.urlBuilder = new WmsUrlBuilder(config.service, config.layerNames, config.styleNames, config.version,
                  timeString);
              if (config.coordinateSystem) {
                  this.urlBuilder.crs = config.coordinateSystem;
              }
  
              /**
               * The time string passed to this layer's constructor.
               * @type {String}
               * @readonly
               */
              this.timeString = timeString;
          };
  
          WmsLayer.prototype = Object.create(TiledImageLayer.prototype);
  
          /**
           * Forms a configuration object for a specified {@link WmsLayerCapabilities} layer description. The
           * configuration object created and returned is suitable for passing to the WmsLayer constructor.
           * <p>
           *     This method also parses any time dimensions associated with the layer and returns them in the
           *     configuration object's "timeSequences" property. This property is a mixed array of Date objects
           *     and {@link PeriodicTimeSequence} objects describing the dimensions found.
           * @param wmsLayerCapabilities {WmsLayerCapabilities} The WMS layer capabilities to create a configuration for.
           * @returns {{}} A configuration object.
           * @throws {ArgumentError} If the specified WMS layer capabilities is null or undefined.
           */
          WmsLayer.formLayerConfiguration = function (wmsLayerCapabilities) {
              var config = {
                  title: wmsLayerCapabilities.title,
                  version: wmsLayerCapabilities.capability.capsDoc.version
              };
  
              // Determine the layer's sector.
              var bbox = wmsLayerCapabilities.geographicBoundingBox || wmsLayerCapabilities.latLonBoundingBox;
              if (bbox && bbox.westBoundLongitude) {
                  config.sector = new Sector(bbox.southBoundLatitude, bbox.northBoundLatitude,
                      bbox.westBoundLongitude, bbox.eastBoundLongitude);
              } else if (bbox && bbox.minx) {
                  config.sector = new Sector(bbox.miny, bbox.maxy, bbox.minx, bbox.maxx);
              } else {
                  config.sector = Sector.FULL_SPHERE;
              }
  
              // Determine level 0 delta.
              config.levelZeroDelta = new Location(36, 36); // TODO: How to determine best delta
  
              // Determine number of levels.
              config.numLevels = 19; // TODO: How to determine appropriate num levels
  
              config.size = 256;
  
              // Assign layer name.
              config.layerNames = wmsLayerCapabilities.name;
  
              // Determine image format
              var getMapInfo = wmsLayerCapabilities.capability.request.getMap,
                  formats = getMapInfo.formats;
  
              if (formats.indexOf("image/png") >= 0) {
                  config.format = "image/png";
              } else if (formats.indexOf("image/jpeg") >= 0) {
                  config.format = "image/jpeg";
              } else if (formats.indexOf("image/tiff") >= 0) {
                  config.format = "image/tiff";
              } else if (formats.indexOf("image/gif") >= 0) {
                  config.format = "image/gif";
              }
  
              // Determine the GetMap service address.
              config.service = getMapInfo.getUrl;
  
              // Determine the coordinate system to use.
              var coordinateSystems = wmsLayerCapabilities.crses; // WMS 1.3.0 and greater
              if (!coordinateSystems) {
                  coordinateSystems = wmsLayerCapabilities.srses; // WMS 1.1.1 and lower
              }
  
              if (coordinateSystems) {
                  if ((coordinateSystems.indexOf("EPSG:4326") >= 0) || (coordinateSystems.indexOf("epsg:4326") >= 0)) {
                      config.coordinateSystem = "EPSG:4326";
                  } else if ((coordinateSystems.indexOf("CRS84") >= 0) || (coordinateSystems.indexOf("CRS:84") >= 0)) {
                      config.coordinateSystem = "CRS:84";
                  }
              }
  
              var dimensions = WmsLayer.parseTimeDimensions(wmsLayerCapabilities);
              if (dimensions && dimensions.length > 0) {
                  config.timeSequences = dimensions;
              }
  
              return config;
          };
  
          WmsLayer.parseTimeDimensions = function (wmsLayerCapabilities) {
              var dimensions = wmsLayerCapabilities.extents || wmsLayerCapabilities.dimensions,
                  parsedDimensions = null;
  
              if (dimensions) {
                  parsedDimensions = [];
  
                  for (var i = 0; i < dimensions.length; i++) {
                      var dimension = dimensions[i];
  
                      if (dimension.name.toLowerCase() === "time" &&
                          (!dimension.units || dimension.units.toLowerCase() === "iso8601")) {
                          var individualDimensions = dimension.content.split(",");
  
                          for (var j = 0; j < individualDimensions.length; j++) {
                              var individualDimension = individualDimensions[j],
                                  splitDimension = individualDimension.split("/");
  
                              if (splitDimension.length === 1) {
                                  parsedDimensions.push(new Date(individualDimension));
                              } else if (splitDimension.length === 3) {
                                  parsedDimensions.push(new PeriodicTimeSequence(individualDimension));
                              }
                          }
                      }
                  }
              }
  
              return parsedDimensions;
          };
  
          return WmsLayer;
      });