owsServices = (function () {

	var _parentId = "#form-wms";

	var _map = null;

    var _tiposServicos = {
        wms: {
            name: "WMS",
            versions: ["1.1.0", "1.1.1", "1.3.0"]
        },
        wmts: {
            name: "WMTS",
            versions: ["1.0.0"]
        }
    };    

    var _setMap = function (map) {
    	_map = map;
    };

	var _getWMSCapabilities = function (version) {
        var url = $('#wmsUrl').val();  
            
        var xhr = OpenLayers.Request.GET({
            url: url,
            params: {
                SERVICE: "WMS",
                VERSION: version || "1.3.0",
                REQUEST: "GetCapabilities"
            },
            success: function (request) {
                var doc = request.responseXML;
                if (!doc || !doc.documentElement) {
                    doc = request.responseText;
                }

                var readCapabilities = function (doc, version) {
                	var caps = null;

	                var format = new OpenLayers.Format.WMSCapabilities({
	                    version: version,
	                    profile: "INSPIRE",
	                    allowFallback: true
	                });                	

                	try {
                		caps = format.read(doc);
                	} catch(err) {}

                	return caps;
                }

                var capabilities = null;

                capabilities = readCapabilities(doc, version);
                if(capabilities == null && version == '1.3.0') {
                	capabilities = readCapabilities(doc, "1.1.1");
                }
                
                if (capabilities && capabilities.capability && capabilities.capability.layers) {					                	
                	if (capabilities.capability.inspire && capabilities.capability.inspire.metadataUrl) {
                		var metadata = '<div class="top-margin-10"><a class="pull-right" target="_blank" href="' + capabilities.capability.inspire.metadataUrl.url + '">' + $.T('Show Service Metadata') + '</a></div>';

                		$("#div-wms-service", _parentId).empty().html(metadata);
					}

                    var layers = capabilities.capability.layers;
                    for (var i = 0; i < layers.length; i++) {
                    	var layer = layers[i];

                    	if (layer.nestedLayers == null || layer.nestedLayers.length == 0) {
                        	$("#table-wms-results", _parentId).append(_createWMSLayerRecord(capabilities.version, capabilities.capability, layers[i]));
                    	}
                    }

                    $('#div-wms-results', _parentId).show();
                } else {
                	$('.msg-error', '#div-wms-error').html($.T('Service not found or unknown response'));
                	$('#div-wms-error', _parentId).show();
                }

                HideLoading('#form-wms div.panel-body'); 
            },
            failure: function (error) {
            	$('.msg-error', '#div-wms-error').html($.T('Service not found or unknown response'));
           		$('#div-wms-error', _parentId).show();

                HideLoading('#form-wms div.panel-body'); 
            }
        });        
        ShowLoading('#form-wms div.panel-body', true, xhr);
	};


    var _getWMTSCapabilities = function (version) {
        var url = $("#wmsUrl").val() || 'http://62.48.186.158:8082/geoserver/gwc/service/wmts?REQUEST=GetCapabilities';

        url = '/proxy?url=' + encodeURIComponent(url);

	    var formatWMTS = new OpenLayers.Format.WMTSCapabilities({
	        /**
	         * This particular service is not in compliance with the WMTS spec and
	         * is providing coordinates in y, x order regardless of the CRS.  To
	         * work around this, we can provide the format a table of CRS URN that
	         * should be considered y, x order.  These will extend the defaults on
	         * the format.
	         */
	        yx: {
	            "urn:ogc:def:crs:EPSG::900913": true
	        }
	    });        

        OpenLayers.Request.GET({
            url: url,
            params: {
                SERVICE: "WMTS",
                VERSION: version || "1.0.0",
                REQUEST: "GetCapabilities"
            },
            success: function (request) {                
                var doc = request.responseXML;
                if (!doc || !doc.documentElement) {
                    doc = request.responseText;
                }
                var capabilities = formatWMTS.read(doc);              

                if (capabilities.contents && capabilities.contents.layers) {
                    var layers = capabilities.contents.layers;
                    for (var i = 0; i < layers.length; i++) {
                        $("#table-wms-results").append(_createWMTSLayerRecord(url, version || "1.0.0", layers[i]));
                    }
                } else {
					//TODO
                }
            },
            failure: function () {
            	//TODO
            }
        });
    };

    function _createWMSLayerRecord(version, capability, layer) {
        var snippet = "<tr><td>";
        var options = "";
        var links = "";

        var supported = false;
        var crs = "";

        if (layer.name && layer.name != "") {
            var req = capability.request.getmap.get.href;

            $.each(layer.srs, function (key, value) {
                if (key == "EPSG:3857") {
                    supported = true;
                    crs = key;
                    return false;
                }
            });
            if (!supported) {
                $.each(layer.srs, function (key, value) {
                    if (key == "EPSG:900913" || key == "EPSG:3785" || key == "ESRI:102113" || key == "ESRI:102100" || key == "EPSG:102113" || key == "EPSG:102100") {
                        supported = true;
                        crs = key;
                        return false;
                    }
                });
            }

            if (supported) {
                links += '<span class="btn btn-primary btn-sm add-layer pull-right" data-service-type="wms" data-service-version="' + version + '" data-url="' + req + '" data-layer-name="' + layer.name + '" data-layer-title="' + layer.title + '" data-layer-crs="' + crs + '">' + $.T('Add to Map') + '</span>';
            } else {
                links += '<div class="alert alert-danger" style="position: inherit; left: 0px;right: 0px;">' + $.T('Coordinate reference sytem not supported') + '</div>';
            }
        }


        var extent = '';
        if (layer.llbbox && layer.llbbox.length > 0) {
            extent = layer.llbbox.join(",");
        }

        var title = '<a class="a-record" title="' + layer.title + '" href="#" data-extent-bbox="' + extent + '">' + layer.title + '</a>';
        snippet += '<h5>' + title + '</h5>';
        snippet += '<p class="muted">' + (layer.abstract || '') + '</p>';
        snippet += options;
		snippet += links;
        snippet += '</td></tr>';

        return snippet;
    };	

    function _createWMTSLayerRecord(url, version, layer) {
        var snippet = "<tr><td>";
        var options = "";
        var links = "";

        if (layer.identifier && layer.identifier != "") {
            var req = url;

            links += '<span class="btn btn-primary add-layer pull-right" data-service-type="wmts" data-service-version="' + version + '" data-url="' + req + '" data-layer-name="' + layer.identifier + '" data-layer-title="' + layer.title + '">' + $.T('Add to map') + '</span>';
        }
        
        var tilematrixsets = '<select id="tileMatrixSets">';
        for (var i = 0; i < layer.tileMatrixSetLinks.length; i++) {
            var matrix = layer.tileMatrixSetLinks[i].tileMatrixSet;
            tilematrixsets = tilematrixsets + '<option value="' + matrix + '">' + matrix + '</option>';
        }
        tilematrixsets = tilematrixsets + '</select>';

        var title = '<a class="a-record" title="' + layer.title + '" href="#">' + layer.title + '</a>';
        snippet += '<h5>' + title + '</h5>';
        snippet += '<p>' + (layer.abstract || '') + '</p>';
        snippet += tilematrixsets;
        snippet += options;
        snippet += links;
        snippet += '</td></tr>';

        return snippet;
    }	

	function _addWMSLayer(url, map, layers, format, transparent, title, crs, tiled, version, styles, group, name, addToMap) {

		var m = _map || map;
		var l;

		var projection = ol.proj.get(crs);


		if (tiled) {
			l = new ol.layer.Tile({
			    source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
			      url: url,
			      params: {'LAYERS': layers, 'STYLES': styles || '','VERSION': version, 'TILED': true}
			    })),
                name: name || '',
		        title: title,
                group: group || ''
			  });
		} else {
			l = new ol.layer.Image({			    
			    source: new ol.source.ImageWMS({
			      url: url,
			      params: {'LAYERS': layers, 'STYLES': styles || '', 'VERSION': version }
			    }),
                name: name || '',
			    title: title,
                group: group || ''                
			  })			
		}

        if (addToMap == null || addToMap) {
		  m.addLayer(l);
        }

        return l;
	};

    var _addWMTSLayer = function (url, map, id, layers, tilematrixset, format, transparent, attribution, version) {
    	var m = _map || map;

    	var projection = ol.proj.get('EPSG:3857');
		var projectionExtent = projection.getExtent();

		var size = ol.extent.getWidth(projectionExtent) / 256;
		var resolutions = new Array(14);
		var matrixIds = new Array(14);
		for (var z = 0; z < 14; ++z) {
		  // generate resolutions and matrixIds arrays for this WMTS
		  resolutions[z] = size / Math.pow(2, z);
		  matrixIds[z] = z;
		}

		var attribution = new ol.Attribution({
		  html: 'Tiles &copy; <a href="http://services.arcgisonline.com/arcgis/rest/' +
		      'services/Demographics/USA_Population_Density/MapServer/">ArcGIS</a>'
		});		

		var l = new ol.layer.Tile({
		    opacity: 0.7,
			extent: projectionExtent,
			source: new ol.source.WMTS({
		        attributions: [attribution],
		        url: 'http://62.48.186.158:8082/geoserver/gwc/service/wmts',
		        layer: layers,
		        matrixSet: tilematrixset, //'EPSG:3857',
		        format: format,
		        projection: projection,
		        tileGrid: new ol.tilegrid.WMTS({
		          origin: ol.extent.getTopLeft(projectionExtent),
		          resolutions: resolutions,
		          matrixIds: matrixIds
		        }),
		        style: 'default'
		      })
		    });

	    m.addLayer(l);
    };

    $('#serviceType', _parentId).change(function (e) {                
        var tipo = $(this).val();        
        $('#serviceVersion', _parentId).empty();

        for (var i = 0; i < _tiposServicos[tipo].versions.length; i++) {
            $('#serviceVersion', _parentId).append('<option value="' + _tiposServicos[tipo].versions[i] + '">' + _tiposServicos[tipo].versions[i] + '</option>');
        }
    });   

    $('#serviceList', _parentId).on("click", "li", function(event) {			
    	if ($('a', this).data('url')) {
    		var url = $('a', this).data('url');
  			$('#wmsUrl', _parentId).val(url);	

  			if($('a', this).data('version')) {
  				var version = $('a', this).data('version');
  				$('#serviceVersion', _parentId).val(version);
  			} else {
  				$('#serviceVersion', _parentId).val('1.3.0');
  			}

  			if($('a', this).data('ignore-service-url')) {
  				var ignore = $('a', this).data('ignore-service-url');
  				$('#ignorarUrlServico', _parentId).prop('checked', ignore);
  			} else {
  				$('#ignorarUrlServico', _parentId).prop('checked', false);
  			}

  			if($('a', this).data('tiled')) {
  				var tiled = $('a', this).data('tiled');
  				$('#tiled', _parentId).prop('checked', tiled);
  			} else {
  				$('#tiled', _parentId).prop('checked', true);
  			}

			$('#table-wms-results', _parentId).empty();
			$('#div-wms-results', _parentId).hide();
			$('#div-wms-error', _parentId).hide();
    	}
    });

	$('#btnWMS', _parentId).on("click", function (e) {
		var type = $('#serviceType', _parentId).val();
		var version = $('#serviceVersion', _parentId).val();	 
		
		$('#table-wms-results', _parentId).empty();
		$('#div-wms-results', _parentId).hide();
		$('#div-wms-error', _parentId).hide();

		if ($('#wmsUrl', _parentId).val() == '') {
			$('.msg-error', '#div-wms-error').html('Type service Url.');
            $('#div-wms-error', _parentId).show();
		} else {
			if (type == 'wmts') {
				_getWMTSCapabilities(version);
			} else {
				_getWMSCapabilities(version);
			}
		}		
	});

    $('#btnFilterLayers', _parentId).click(function (e) {
        var filter = $('#txtLayersFilter', _parentId).val();
        
        if (filter && filter != "") {
            $('tr', '#table-wms-results').hide();
            $("h5:contains('" + filter + "')", "#table-wms-results tr").closest("tr").show();
        } else {
            $('tr', '#table-wms-results').show();
        }
    });

    $('#btnClearFilter', _parentId).click(function () {
        $('#txtLayersFilter', _parentId).val('');
        $('tr', '#table-wms-results').show();
    });	

    $("#table-wms-results", _parentId).on("click", ".a-record", function(event) {
        var extentBBox = $(this).data('extent-bbox');
        var extentSRS = 'EPSG:4326';

        if (extentBBox && extentBBox != '') {
            var extent = extentBBox.split(',');
            var poly = getPolygonFromExtent(extent);

            var geom = poly.transform(extentSRS, _map.getView().getProjection().getCode());
            _map.getView().fitExtent(geom.getExtent(),  _map.getSize());                         
        }
    });


	$("#table-wms-results", _parentId).on("click", ".add-layer", function(event) {
		var url = $(this).attr('data-url');	
		var version = $(this).attr('data-service-version');
		var layer_name = $(this).attr('data-layer-name');
		var layer_title = $(this).attr('data-layer-title');
		var layer_crs = $(this).attr('data-layer-crs');

		var service_type = $(this).attr('data-service-type');

		var tiled = $("#tiled", _parentId).is(':checked');

        if ($("#ignorarUrlServico", _parentId).is(':checked')) {
            url = $("#wmsUrl", _parentId).val();
        }		        

		$('.layers-control').show();

		if (service_type == "wms") {
			var wms = _addWMSLayer(url, _map, layer_name, 'image/png', true, layer_title, layer_crs, tiled, version);

            if (wms) {
                if ($('a.a-record', $(this).parent()) && $('a.a-record', $(this).parent()).length > 0) {
                    var el = $('a.a-record', $(this).parent())[0];

                    var extentBBox = $(el).data('extent-bbox');
                    var extentSRS = 'EPSG:4326';              

                    if (extentBBox && extentBBox != '') {
                        var extent = extentBBox.split(',');
                        var poly = getPolygonFromExtent(extent);

                        var geom = poly.transform(extentSRS, _map.getView().getProjection().getCode());
                        _map.getView().fitExtent(geom.getExtent(),  _map.getSize());                         
                    }
                }
            }

		} else if (service_type == "wmts") {
			var tilematrixset = "EPSG:900913";

			var wmts = _addWMTSLayer(url, _map, layer_name, tilematrixset, 'image/png', true, layer_title, version);
		}
	});

    return {
        setMap: _setMap,
        addWMSLayer: _addWMSLayer,
        addWMTSLayer: _addWMTSLayer
    }

} ());