import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
import { ConfirmationService, MenuItem, MessageService } from 'primeng/api';
import { Extent } from 'ol/extent';
import { Group, Tile, Vector as VectorLayer } from 'ol/layer';
import {OSM, TileArcGISRest, TileWMS, Vector as VectorSource} from 'ol/source';
import GeoJSON from 'ol/format/GeoJSON';
import { transform, transformExtent } from 'ol/proj';
import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style';
import View from 'ol/View';
import { Unit } from '../../../shared/api/endpoints/models/unit';
import { Lastpos } from '../../../shared/api/endpoints/models/lastpos';
import { Drivers } from '../../../shared/api/endpoints/models/drivers';
import { GeneralInfo } from '../../../shared/api/endpoints/models/general-info';
import { Sensor } from '../../../shared/api/endpoints/models/sensor';
import {
  HsConfig,
  HsMapService,
  HsLayerManagerService,
  HsLayerEditorService,
  HsEventBusService
} from 'hslayers-ng';
import { environment } from '../../../../environments/environment';
import Geometry from 'ol/geom/Geometry';

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.scss']
})
export class MapComponent implements OnInit, OnDestroy, OnChanges {

  @Input('units') units:
      Array<{ drivers?: Drivers; generalInfo?: GeneralInfo; holder?: any; lastpos?: Lastpos; sensors?: Array<Sensor>; unit?: Unit }>;
  mapReady = false;
  dataReady = false;
  unitsLayer: VectorLayer<VectorSource<Geometry>>;

  constructor(
    private confirmationService: ConfirmationService,
    private messageService: MessageService,
    public HsConfig: HsConfig,
    public HsMapService: HsMapService,
    public HsLayerManagerService: HsLayerManagerService,
    public HsLayerEditorService: HsLayerEditorService,
    public HsEventBusService: HsEventBusService
  ) {
    this.HsConfig.update({
      assetsPath: environment.hslayersAssetsPath,
      popUpDisplay: 'click',
      useProxy: false,
      proxyPrefix: window.location.hostname.includes('localhost')
        ? `${window.location.protocol}//${window.location.hostname}:8085/`
        : '/proxy/',
      box_layers: [
        new Group({
          properties: {
            title: 'Base layer',
          },
          layers: [
            new Tile({
              source: new OSM(),
              visible: true,
              properties: {
                title: 'OpenStreetMap',
                base: true,
                removable: false
              }
            }),
            new Tile({
              visible: false,
              source: new TileWMS({
                url: 'https://ags.cuzk.gov.cz/arcgis1/services/ORTOFOTO_WM/MapServer/WMSServer',
                crossOrigin: 'anonymous',
                params: {
                  LAYERS: '0',
                  TILED: true,
                  FORMAT: 'image/jpeg',
                  VERSION: '1.3.0' // Explicit version helps handshake
                },
                attributions: '&copy; <a href="https://geoportal.cuzk.cz" target="_blank">ČÚZK</a>'
              }),
              // HSLayers-specific properties
              properties: {
                title: 'Ortofoto ČÚZK',
                base: true,
                removable: false,
                path: 'Base layer',
                thumbnail: 'hslayers-ng/assets/img/orto.png'
              }
            })
          ]
        })
      ],
      // default_layers: this.loadLayers(),
      componentsEnabled: {
        sidebar: true,
        toolbar: false,
        guiOverlay: true,
        drawToolbar: false,
        searchToolbar: false,
        measureToolbar: false,
        sensors: false,
        crossfilter: false,
        geolocationButton: false,
        tracking: false,
        mapControls: true,
        basemapGallery: true
      },
      panelsEnabled: {
        info: true, // (true by default),
        layermanager: false
      },
      sidebarPosition: 'invisible',
      queryPoint: 'hidden',
      default_view: new View({
        maxZoom: 17
      //    center: [1873444.3416929364, 6286508.646897761], // Latitude longitude    to Spherical Mercator
      //    extent: [1871197.0792499082, 6282949.4051418, 1873509.6915773677, 6287134.61866585],
      //    multiWorld: false,
          // zoom: 6
      })
    }
    );
  }

  ngOnInit(): void {
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.units) {
      // this.dataReady = true;

      // if (this.mapReady)
      this.HsMapService.loaded().then((map) => {
        this.initMap();
        const mapObj = this.HsMapService.getMap();

        const unitsExtent: Extent = this.unitsLayer.getSource().getExtent();
        mapObj.getView().fit(unitsExtent, { padding: [50, 50, 50, 50], size: mapObj.getSize() });

        mapObj.on('pointermove', function (evt) {
          const hit = this.forEachFeatureAtPixel(evt.pixel, function (feature, layer) {
            return true;
          });
          if (hit) {
            this.getTargetElement().style.cursor = 'pointer';
          } else {
            this.getTargetElement().style.cursor = '';
          }
        });
      });
    }
  }

  /**
   * Unsubscribe after leaving
   */
  ngOnDestroy(): void {
  }

  initMap(): void {
    const mapObj = this.HsMapService.getMap();

    this.unitsLayer = this.initUnitsLayer(mapObj);
    mapObj.addLayer(this.unitsLayer);

  //  this.HsMapService.map.on('click', function (evt) {
  //    var feature = this.HsMapService.map.forEachFeatureAtPixel(evt.pixel,
  //      function (feature) {
  //        return feature;
  //      });

  //    if (feature) {
  //      let unitId = feature.getProperties()['unitId'];
  //      window.open('/#/dashboard / unit /' + unitId);
  //    }
  //  })
  }

  /**
   * Crete vector layer from units positions
   */
  initUnitsLayer(map: any): any {
    const geoJsonUnits = {
      type: 'FeatureCollection',
      crs: {
        type: 'name',
        properties: {
          name: 'EPSG:3857',
        }
      },
      features: []
    };

    geoJsonUnits.features = this.units ? this.units.filter(u => (u.lastpos.position.x !== 0))
                                          .map(u => this.getUnitPos(u.lastpos, u.unit)) : [];

    const vectorSource = new VectorSource({
      features: new GeoJSON().readFeatures(geoJsonUnits),
    });
    vectorSource.on('addfeature', function () {
      map.getView().fit(vectorSource.getExtent(), { padding: [50, 50, 50, 50]});
    });

    const vectorLayer = new VectorLayer({
      source: vectorSource,
      style: this.styleFunction,
      properties: {
        popUp: {
          displayFunction (feature) {
            return `<table>
              <tr>
                <th>Unit name</th>
                <td>${feature.get('title')}</td>
              </tr>
              <tr>
                <th>Unit ID</th>
                <td>${feature.get('id')}</td>
              </tr>
            </table>
            <button class="p-button-primary" style="display: block; margin: auto; margin-bottom: 10px;"><a class="white" href="/dashboard/unit/${feature.get('id')}?unitDescription=${feature.get('title')}" target="_blank">Open Unit detail...</a></button>
            `;
          }
        //  attributes: [
        //    {
        //      attribute: 'id',
        //      label: 'Unit ID'
        //    },
        //    {
        //      attribute: 'online',
        //      label: 'Online',
        //      displayFunction: function (val) {
        //        return '<span class="' + (val ? 'far fa-check-square' : 'far fa-square') + '"></span>';
        //      }
        //    },
        //    {
        //      attribute: 'test',
        //      label: 'test'
        //    },
        //    {
        //      attribute: 'id',
        //      label: 'Detail',
        //      displayFunction: function (val) {
        //        return '<a class="white" href="/#/dashboard/unit/' + val + '" target="_blank">open unit detail...</a>';
        //      }
        //    }
        //  ]
        }
      }
    });

    return vectorLayer;
  }

  styleFunction(feature: any): Style {
    return new Style({
      image: new CircleStyle({
        radius: 5,
        fill: new Fill({
          color: 'red'
        }),
        stroke: new Stroke({
          color: 'blue',
          width: 2
        })
      })
    })
  }

  getUnitPos(pos: Lastpos, unit: Unit): any {
    return {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [pos.position.x, pos.position.y]
      },
      properties: {
        id: unit.unitId,
        title: unit.description,
        online: pos.attributes.is_online,
        moving: pos.attributes.is_moving
      }
    }
  }
}
