import {WMTSCapabilities, MVT, GeoJSON } from 'ol/format';
import {optionsFromCapabilities} from 'ol/source/WMTS';
import {OSM, TileWMS, WMTS, VectorTile as VectorTileSource, Vector as VectorSource} from 'ol/source';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import VectorTileLayer from 'ol/layer/VectorTile';
import {bbox as bboxStrategy} from 'ol/loadingstrategy';
import { DOMAIN_BASE, GEOSERVER_NAME} from '../../Constants';

/**
 * Obtenemos una capa del mapa por su id
 */
 export function getLayerById (map, layerId) {
    var layers = map.getLayers().getArray()
	for (var i=0; i<layers.length; i++) {
		if (layers[i].getProperties().id === layerId) {
			return layers[i];
		}
	}
};

/**
 * TODO
 */
export function loadBaseLayers (map, baseLayers) {
    for (let i=0; i<baseLayers.length; i++) {
        let baseLayer = baseLayers[i];
        let layerId = 'baselayer-' + baseLayer.id;

        if (baseLayer.type === 'osm') {
            addOsmLayer(map, layerId, baseLayer.title, baseLayer.visible, i, true);

        } else if (baseLayer.type === 'wms') {
            createWMSTileLayer(map, baseLayer.url, null, layerId, null, baseLayer.name, baseLayer.title, baseLayer.visible, i, true, false);

        } else if (baseLayer.type === 'wmts') {
            createWMTSTileLayer(map, baseLayer.url, layerId, baseLayer.name, baseLayer.title, baseLayer.visible, i, true);
        }
    }
};

/**
 * TODO
 */
export function loadLayers (map, layerTree) {
    for (let i in layerTree) {
        if (!layerTree[i].isLayer) {
            loadLayers(map, layerTree[i].children);

        } else {
            let order = i + 1000;
            let layerId = layerTree[i].key;
            createWMSTileLayer (map, layerTree[i].wms_url, layerTree[i].wfs_url, layerId, layerTree[i].ws, layerTree[i].name, layerTree[i].title, layerTree[i].visible, order, false, layerTree[i].is_VPostgis);
        }
    }
};

/**
 * TODO
 */
 export function addOsmLayer (map, layerId, title, visible, order, baseLayer) {
    const source = new OSM();
    let layer = new TileLayer({
        id: layerId,
        label: title,
        visible: visible,
        source: source
    });
    layer.id = layerId;
    layer.title = title;
    layer.baselayer = baseLayer;
    layer.default_baselayer = visible;
    layer.setZIndex(parseInt(order));
    map.addLayer(layer);
};

/**
 * TODO
 */
 export function createWMSTileLayer (map, wmsUrl, wfsUrl, layerId, workspace, layerName, title, visible, order, baseLayer, isVPostgis) {
    let wmsParams = {
        'LAYERS': layerName,
        'FORMAT': 'image/png',
        'VERSION': '1.3.0'
    };

    let source = new TileWMS({
        url: wmsUrl,
        visible: visible,
        params: wmsParams,
        serverType: 'geoserver'
    });
    let layer = new TileLayer({
        id: layerId,
        title: title,
        source: source,
        visible: visible
    });
    layer.id = layerId;
    layer.type = 'wms';
    layer.layer_name = layerName;
    layer.title = title;
    layer.workspace = workspace;
    layer.baselayer = baseLayer;
    layer.default_baselayer = visible;
    layer.is_VPostgis = isVPostgis;
    layer.wfs_url = wfsUrl;
    layer.setZIndex(parseInt(order));
    map.addLayer(layer);
};

/**
 * TODO
 */
 export function createWMTSTileLayer (map, wmtsUrl, layerId, name, title, visible, order, baseLayer) {
    let url = new URL(wmtsUrl)
    url.search = new URLSearchParams({
        service: 'wmts',
        version: '1.0.0',
        request: 'getCapabilities'
    });
    fetch(url)
    .then(function(response){
        return response.text();
    })
    .then(function(text) {
        let domParser = new DOMParser();
        let xmlDoc = domParser.parseFromString(text, "text/xml");
        let parser = new WMTSCapabilities();
        let result = parser.read(xmlDoc);
        
        let options = optionsFromCapabilities(result, {
            matrixSet: 'GMEPSG3857',
            layer: name
        });
        options.crossOrigin = 'anonymous';
        
        let source = new WMTS((options));
        let layer = new TileLayer({
            id: layerId,
            source: source,
            visible: visible
        });
        layer.id = layerId;
        layer.type = 'wmts';
        layer.title = title;
        layer.baselayer = baseLayer;
        layer.default_baselayer = visible;
        layer.setZIndex(parseInt(order));
        map.addLayer(layer);
    });
};

/**
 * TODO
 */
 export function createVectorTileLayer (map, layerId, workspace, name, title, visible, order, style, minZoom, maxZoom) {
    let projection_epsg = '3857';
    let source = new VectorTileSource({
        //tileGrid: createXYZ({ maxZoom: 21 }),
        format: new MVT(),
        url: DOMAIN_BASE + '/' + GEOSERVER_NAME + '/gwc/service/tms/1.0.0/' + workspace + ':' + name +
            '@EPSG%3A' + projection_epsg + '@pbf/{z}/{x}/{-y}.pbf',
        tileSize: 256,
        tileLoadFunction: function(tile, url) {
            tile.setLoader(function(extent, resolution, projection) {
              fetch(url).then(function(response) {
                response.arrayBuffer().then(function(data) {
                  const format = tile.getFormat() // ol/format/MVT configured as source format
                  const features = format.readFeatures(data, {
                    extent: extent,
                    featureProjection: projection
                  });
                  tile.setFeatures(features);
                });
              });
            });
          }
    });

    let layer = new VectorTileLayer({
        id: layerId,
        visible: visible,
        style: style,
        renderMode: 'hybrid',
        source: source,
        minZoom: minZoom,
        maxZoom: maxZoom/*,
        renderMode: 'vector'*/
    });

    layer.id = layerId;
    layer.type = 'vector-tile';
    layer.baselayer = false;
    layer.setZIndex(parseInt(order));
    map.addLayer(layer);
};

/**
 * TODO
 */
 export function createWfsLayer (map, layerId, workspace, name, title, visible, order, style, minZoom, maxZoom) {
    let projection_epsg = '3857';
    const source = new VectorSource({
        format: new GeoJSON(),
        url: function (extent) {
            return (
                DOMAIN_BASE + '/' + GEOSERVER_NAME + '/wfs?service=WFS&' +
                'version=1.1.0&request=GetFeature&typename=' + workspace + ':' + name + '&' +
                'outputFormat=application/json&srsname=EPSG:' + projection_epsg + '&' +
                'bbox=' +
                extent.join(',') +
                ',EPSG:3857'
            );
        },
        strategy: bboxStrategy,
    });
      
    const layer = new VectorLayer({
        id: layerId,
        visible: visible,
        source: source,
        minZoom: minZoom,
        maxZoom: maxZoom,
        style: style
    });

    layer.id = layerId;
    layer.type = 'vector-tile';
    layer.title = title;
    layer.showLegend = true;
    layer.baselayer = false;
    layer.setZIndex(parseInt(order));
    map.addLayer(layer);
};