import {
  AfterViewInit,
  Component,
  EventEmitter,
  Input,
  OnDestroy,
  OnInit,
  Output,
} from "@angular/core";

import * as moment from "moment-timezone";
import { ContactService } from "../contact.service";
import { MoveMarkerService } from "../location/move-marker.service";
import { LocationCommanService } from "../location/service/location-comman.service";
declare var mapboxgl: any;
declare var ol: any;
declare var L: any;
declare var google: any;
declare var maplibregl: any;
declare var MaplibreInspect: any;
// declare var MarkerClusterer: any;
declare var InfoBox: any;
declare var mapboxgl: any;
@Component({
  selector: "app-open-map",
  templateUrl: "./open-map.component.html",
  styleUrls: ["./open-map.component.scss"],
})
export class OpenMapComponent implements OnDestroy, AfterViewInit {
  historyMode = {
    isParking: false,
    isIdle: false,
    isPoints: false,
  };
  isHistoryPlay = false;
  isLocationTab = false;
  uniqueIdForHistory = "1302023";
  stoppagesData = {
    item: {},
    displayMarkers: [],
  };
  activeHistoryTrack: any = {
    endMarker: "",
    vehicleMarker: "",
    lastTracks: {},
    currentPath: {
      flag: "init",
    },
    historyTracks: [],
    activeTrackIndex: 0,
    currentVehicleIndex: 0,
    getTrack: () => {
      return this.activeHistoryTrack.historyTracks[
        this.activeHistoryTrack.activeTrackIndex
      ];
    },
  };
  speed = 1;
  map: any;
  allDevices: any[] = [];
  masterDevicesList: any[] = [];
  markersList = {};
  filterDevicesList: any[] = [];
  historyTracks: any = {
    movePath: {},
    linepath: [],
  };
  constructor(
    private _moveMarkerService: MoveMarkerService,
    private contactService: ContactService,
    private _locationCommanService: LocationCommanService
  ) {}
  @Output() socketListner: EventEmitter<any> = new EventEmitter<any>();
  @Input() set socketData(value: any) {
    if (value) {
      this.updateMarker(value);
    }
  }

  @Input() geoFenceList: any[] = [];
  @Input() set devicesList(value: any[]) {
    setTimeout(() => {
      this.setMasterDeviceList(value);
    }, 1000);
  }
  setMasterDeviceList(list) {
    this.masterDevicesList = list;
    this.getFinalDeviceList();
  }
  getFinalDeviceList() {
    console.log("db_open_map_91");
    this._moveMarkerService.forceStopMarkerMove = true;
    this.socketListner.next({
      type: "remove",
      list: this.allDevices.map((d) => d.Device_ID),
    });
    this.clearMap(() => {
      if (this.masterDevicesList.length) {
        this.allDevices = this.masterDevicesList.filter(
          (mDevice) =>
            mDevice.checked &&
            mDevice.last_loc &&
            mDevice.last_loc.coordinates.length &&
            mDevice.last_loc.coordinates[0] != 0
        );
        if (!this.isLocationTab && this.allDevices.length > 1) {
          this.allDevices = [this.allDevices[0]];
        }

        // if deviceMore than 500 then split list
        if (this.allDevices.length > 500) {
          this.allDevices = this.allDevices.slice(0, 500);
        }
        console.log("db_open_map_114");
        this.socketListner.next({
          type: "add",
          list: this.allDevices.map((d) => d.Device_ID),
        });
        this.displayALLMarker();
        this.setZoomAndCenter(this.map, this.allDevices.length == 1 ? 16 : 10);
      } else {
      }
    });
  }

  toggleMapDetails(isLocation = true) {
    this.isLocationTab = isLocation;
    if (isLocation) {
      this.getFinalDeviceList();

      this._moveMarkerService.removeAllStoppage(this.stoppagesData);
      this.removeDataBefore();
    } else {
      console.log("db_open_map_134");
      this.socketListner.next({
        type: "remove",
        list: this.allDevices.map((d) => d.Device_ID),
      });
      this.clearMap(() => {
        if (this.activeHistoryTrack.historyTracks.length) {
          this.setHistoryTrack(this.uniqueIdForHistory, [], [], 0, true);
          this.displayStoppage();
        }
      });
    }
  }

  clearMap(clearDone = () => {}) {
    setTimeout(() => {
      for (const [key, value] of Object.entries(this.markersList)) {
        try {
          this.markersList[key].marker.remove();
          delete this.markersList[key];
        } catch (error) {}
      }
      this.allDevices = [];
      this.markersList = {};
      clearDone();
    }, 100);
  }
  ngAfterViewInit() {
    var preference = maplibregl.supported() ? "vector" : "raster";
    if (preference == "vector") {
      if (maplibregl.getRTLTextPluginStatus() === "unavailable") {
        maplibregl.setRTLTextPlugin(
          "https://map.oneqlik.in/maps/mapbox-gl-rtl-text.js"
        );
      }

      setTimeout(() => {
        this.map = new maplibregl.Map({
          container: "newmap1",
          style: "https://map.oneqlik.in/maps/styles/test-style/style.json",
          hash: true,
          maplibreLogo: true,
          center: [27.51, 77.01],
          zoom: 6,
        });
        this.map.addControl(
          new maplibregl.NavigationControl({
            visualizePitch: true,
            showZoom: true,
            showCompass: true,
          })
        );
        this.map.addControl(
          new MaplibreInspect({
            showMapPopupOnHover: false,
            showInspectMapPopupOnHover: false,
            selectThreshold: 5,
          })
        );
        this.displayALLMarker();
        this.setZoomAndCenter(this.map);
      }, 10);

      setTimeout(function () {
        new L.Hash(this.map);
      }, 100);
    } else {
      var map = L.map("newmap1", { zoomControl: false });
      new L.Control.Zoom({ position: "topright" }).addTo(map);

      var tile_urls = [],
        tile_attribution,
        tile_minzoom,
        tile_maxzoom;

      var url = "https://map.oneqlik.in/maps/styles/test-style.json";
      var req = new XMLHttpRequest();
      req.overrideMimeType("application/json");
      req.open("GET", url, true);
      req.onload = function () {
        var jsonResponse = JSON.parse(req.responseText);
        for (let key in jsonResponse) {
          var keyl = key.toLowerCase();
          switch (keyl) {
            case "tiles":
              tile_urls = jsonResponse[key];
              break;
            case "attribution":
              tile_attribution = jsonResponse[key];
              break;
            case "minzoom":
              tile_minzoom = jsonResponse[key];
              break;
            case "maxzoom":
              tile_maxzoom = jsonResponse[key];
              break;
          }
        }

        for (let tile_url in tile_urls) {
          L.tileLayer(tile_urls[tile_url], {
            minZoom: tile_minzoom,
            maxZoom: tile_maxzoom,
            attribution: tile_attribution,
          }).addTo(map);
        }

        map.eachLayer(function (layer) {
          // do not add scale prefix even if retina display is detected
          layer.scalePrefix = ".";
        });
      };
      req.send(null);
    }

    this.checkAndSetIntervalMap();
  }
  updateMarker(device) {
    if (device && this.markersList[device.Device_ID]) {
      if (device.status != this.markersList[device.Device_ID].rStatus) {
        this.markersList[device.Device_ID].rStatus = device.status;
        let url = this._locationCommanService.iconSelector(
          device.status,
          device.iconType
        );
        let getMarkerImg = document.getElementById(
          "marker_" + device.Device_ID
        );
        getMarkerImg.style.backgroundImage = `url(${url})`;
      }
      const marker = this.markersList[device.Device_ID];
      //marker.setLngLat(device.last_loc.coordinates);
      marker.id = new Date().getMilliseconds();
      // const rotated = document.getElementById('marker_' + device.Device_ID);
      // var re = /[0-9A-Fa-f]{6}/g;
      // let rotationDegree;
      // if (re.test(device.heading)) {
      //   rotationDegree = parseInt(device.heading, 16);
      // }
      // else {
      //   rotationDegree = device.heading - 180;
      // }

      // rotated.style.transform = `rotate(${rotationDegree}deg)`;
      marker.popupContent = {
        Device_Name: device.Device_Name
          ? device.Device_Name
          : marker.popupContent.Device_Name,
        lastUpdate: device.last_ping_on
          ? device.last_ping_on
          : marker.popupContent.last_ping_on,
        gpsTracking: device.gpsTracking
          ? device.gpsTracking
          : marker.popupContent.gpsTracking,
        gsm_signal: device.gsmSignal
          ? device.gsmSignal
          : marker.popupContent.gsmSignal,
        DriverNumber: device.contact_number
          ? device.contact_number
          : marker.popupContent.contact_number,
        DriverName: device.driver_name
          ? device.driver_name
          : marker.popupContent.driver_name,
        last_speed: device.last_speed
          ? device.last_speed
          : marker.popupContent.last_speed,
        status_updated_at: device.status_updated_at
          ? device.status_updated_at
          : marker.popupContent.status_updated_at,
      };
      //marker.marker.setRotation(rotationDegree);
      marker.popup.setHTML(
        this._locationCommanService.getPopupHTML(marker.popupContent)
      );
      if (device.last_location) {
        this._moveMarkerService.animatedMove(
          marker,
          marker.marker.getLngLat(),
          device.last_location,
          this.map,
          this.allDevices.length == 1
        );

        let heading: any = this._locationCommanService.calculateHeading(
          marker.marker.getLngLat(),
          {
            lat: device.last_location.lat,
            lng: device.last_location.long,
          }
        );
        if (heading[0]) {
          heading[0] = -heading[0];
        }
        this.imageRoatedById("marker_" + device.Device_ID, heading);
      }
    }
  }
  displayALLMarker() {
    if (this.map && this.allDevices.length) {
      this.allDevices.forEach((device) => {
        this.drawMarker(device);
      });
    }
  }
  setZoomAndCenter(map, zoomLevel = 10, latLng = "") {
    if (map) {
      if (!latLng && this.allDevices.length) {
        map.setCenter(this.allDevices[0].last_loc.coordinates);
      } else if (latLng) {
        map.setCenter(latLng);
      }
      map.zoomTo(zoomLevel, {
        duration: 2000,
      });
    }
  }
  drawMarker(device) {
    const marker = {
      type: "Feature",
      properties: {
        message: "Not found",
        iconSize: [48, 48],
      },
      geometry: {
        type: "Point",
        coordinates: [27.51, 77.01],
      },
    };
    if (device.iconType == "bus") {
      marker.properties.iconSize = [25, 48];
    }
    marker.properties.message = device.Device_Name;
    marker.geometry.coordinates = device.last_loc.coordinates;
    let url = this._locationCommanService.iconSelector(
      device.status,
      device.iconType
    );
    let placeholder = device.status + "_" + device.iconType;
    const el: any = document.createElement("div");
    const width = marker.properties.iconSize[0];
    const height = marker.properties.iconSize[1];

    const elImg: any = document.createElement("div");
    const label = document.createElement("div");

    label.innerHTML = `<span class="open-map-label" placeholder="${placeholder}">${device.Device_Name}</span>`;
    el.appendChild(label);
    el.className = "marker";

    elImg.style.backgroundImage = `url(${url})`;

    el.style.width = `${width}px`;
    el.style.height = `${height}px`;
    el.classList.add("marker-map-section");
    elImg.classList.add("marker-mapi-section");
    el.style.backgroundSize = "100%";

    let rotationDegree = this.roatedImage(device.heading);
    elImg.id = "marker_" + device.Device_ID;
    elImg.style.transform = `rotateZ(${rotationDegree}deg)`;
    el.appendChild(elImg);
    //el.rotation =
    el.addEventListener(
      "click",
      (function (dt) {
        return function () {
          console.log("click ev 396=>", dt);
        };
      })(device)
    );

    // Add markers to the map.
    if (!this.markersList[device.Device_ID] && this.map) {
      let popupContent = {
        Device_Name: device.Device_Name,
        lastUpdate: device.last_ping_on,
        gpsTracking: device.gpsTracking,
        gsm_signal: device.gsmSignal,
        DriverNumber: device.contact_number,
        DriverName: device.driver_name,
        last_speed: device.last_speed,
        status_updated_at: device.status_updated_at,
      };
      let popup = new maplibregl.Popup({ offset: 25 })
        .setHTML(this._locationCommanService.getPopupHTML())
        .setMaxWidth("400px");
      let mapMarker = new maplibregl.Marker(el)
        .setLngLat(marker.geometry.coordinates)
        .setPopup(popup)
        // .setRotation(rotationDegree)
        .addTo(this.map);

      this.markersList[device.Device_ID] = {
        marker: mapMarker,
        popup: popup,
        popupContent: popupContent,
        rStatus: device.status,
      };
    }
  }
  roatedImage(degree, minus = 0) {
    return ((degree ? degree - minus : 0) * Math.PI) / 180;
  }
  markerDisplay() {
    this.map.getStyle().layers.forEach((layer) => {
      if (layer.id.match(/line_/g)) {
        this.map.removeLayer(layer.id);
        this.map.removeSource(layer.id);
      }
    });
  }

  intervalTimer;
  checkAndSetIntervalMap() {
    this.intervalTimer = setInterval(() => {
      if (
        this.map &&
        this.allDevices.length == 0 &&
        this.masterDevicesList.length
      ) {
        this.getFinalDeviceList();
        clearInterval(this.intervalTimer);
      } else {
      }
    }, 1000);
  }

  newDrawPolygon(map, geofencesList) {
    if (this.lastGeofenceLayerId) {
      this._locationCommanService.removeSourceById(
        this.map,
        this.lastGeofenceLayerId
      );
    }
    this.lastGeofenceLayerId = "myMap_" + new Date().getTime();
    if (this.lastGeofenceLayerId && geofencesList.length) {
      map.addSource(this.lastGeofenceLayerId, {
        type: "geojson",
        data: {
          type: "FeatureCollection",
          features: geofencesList,
        },
      });
      map.addLayer({
        id: this.lastGeofenceLayerId,
        type: "fill",
        source: this.lastGeofenceLayerId,
        layout: {},
        paint: {
          "fill-color": "#FF0000",
          "fill-opacity": 0.4,
          "fill-outline-color": "#FF0000",
        },
      });
    }
  }
  ngOnDestroy() {
    clearInterval(this.intervalTimer);
  }
  lastGeofenceLayerId = "";
  geofenceAction(isShow, id = "") {
    let newgeofencesList = [];
    this.geoFenceList.forEach((geofence) => {
      if (id) {
        if (id == geofence._id) {
          if (!isShow) {
            newgeofencesList.push({
              type: "Feature",
              geometry: geofence.geofence,
            });
          }
          if (
            geofence.geofence &&
            geofence.geofence.coordinates.length &&
            geofence.geofence.coordinates[0].length &&
            geofence.geofence.coordinates[0][0]
          ) {
            this.setZoomAndCenter(
              this.map,
              10,
              geofence.geofence.coordinates[0][0]
            );
          }
        }
      } else {
        if (isShow) {
          newgeofencesList.push({
            type: "Feature",
            geometry: geofence.geofence,
          });
        } else {
          this._locationCommanService.removeSourceById(
            this.map,
            this.lastGeofenceLayerId
          );
        }
      }
    });
    if (newgeofencesList.length) {
      this.newDrawPolygon(this.map, newgeofencesList);
    }
  }
  historyPathId;

  setHistoryTrack(
    uniqueId,
    historyList,
    linePath,
    selectedIndex,
    isOld = false,
    status = ""
  ) {
    this.pause();
    if (!isOld) {
      if (
        historyList[selectedIndex] &&
        historyList[selectedIndex].dataArrayCoords.length
      ) {
        historyList[selectedIndex].dataArrayCoords =
          historyList[selectedIndex].dataArrayCoords.reverse();
        let cumDistance = 0;
        historyList[selectedIndex].dataArrayCoords.forEach((d) => {
          cumDistance =
            (d.distanceFromPrevious ? parseFloat(d.distanceFromPrevious) : 0) +
            cumDistance;
          d.tCum = cumDistance;
        });
      }
      this.activeHistoryTrack.currentVehicleIndex = 0;
      this.activeHistoryTrack.historyTracks = [
        {
          movePath: historyList[selectedIndex],
          linePath: linePath,
          id: uniqueId,
        },
      ];
      this.activeHistoryTrack.lastTracks[
        this.activeHistoryTrack.activeTrackIndex
      ] = this.activeHistoryTrack.currentVehicleIndex;
      selectedIndex = this.activeHistoryTrack.historyTracks.length - 1;
    } else {
      this.activeHistoryTrack.currentVehicleIndex = this.activeHistoryTrack
        .lastTracks[selectedIndex]
        ? this.activeHistoryTrack.lastTracks[selectedIndex]
        : 0;
      linePath = this.activeHistoryTrack.historyTracks[selectedIndex].linePath;
    }

    if (this.historyPathId) {
      this._locationCommanService.removeSourceById(
        this.map,
        this.historyPathId
      );
    }
    if (this.activeHistoryTrack.endMarker) {
      this.activeHistoryTrack.endMarker.setLngLat(
        linePath[linePath.length - 1]
      );
    } else {
      this.activeHistoryTrack.endMarker = new maplibregl.Marker({
        color: "red",
      })
        .setLngLat(linePath[linePath.length - 1])
        .addTo(this.map);
    }
    if (this.activeHistoryTrack.vehicleMarker) {
      this.activeHistoryTrack.vehicleMarker.remove();
    }
    if (linePath[0]) {
      this.setZoomAndCenter(this.map, 10, linePath[0]);
    }
    this.historyPathId = "line_" + new Date().getTime();

    this.activeHistoryTrack.activeTrackIndex = selectedIndex;
    this.historyTracks = this.activeHistoryTrack.getTrack();
    if (
      this.historyTracks.linePath &&
      this.historyTracks.linePath.length &&
      this.historyTracks.movePath
    ) {
      this._locationCommanService.displayLineDraw(
        this.map,
        this.historyPathId,
        this.historyTracks.linePath
      );
      if (this.historyMode.isPoints) {
        this._locationCommanService.displayPoints(
          this.map,
          this.historyPathId + "_points",
          this.historyTracks.movePath.dataArrayCoords
        );
      }
      this.activeHistoryTrack.currentPath = this.historyTracks.movePath;
      this.getAllAddress();
      this._moveMarkerService.animatedMarker(
        this.activeHistoryTrack,
        this.map,
        this.historyTracks.linePath[0]
      );
    }
  }

  play(index = 0) {
    index = this.activeHistoryTrack.currentVehicleIndex
      ? this.activeHistoryTrack.currentVehicleIndex
      : 0;
    this.isHistoryPlay = true;
    let currentLatLng = {};
    let moveToLatLng = {};
    this.activeHistoryTrack.currentPath.flag = "start";
    if (
      this.activeHistoryTrack.currentPath.flag != "stop" &&
      this.activeHistoryTrack.currentPath.dataArrayCoords[index] &&
      this.activeHistoryTrack.currentPath.dataArrayCoords[index + 1]
    ) {
      currentLatLng = {
        lat: this.activeHistoryTrack.currentPath.dataArrayCoords[index].lat,
        lng: this.activeHistoryTrack.currentPath.dataArrayCoords[index].lng,
      };
      moveToLatLng = {
        lat: this.activeHistoryTrack.currentPath.dataArrayCoords[index + 1].lat,
        lng: this.activeHistoryTrack.currentPath.dataArrayCoords[index + 1].lng,
      };
      let heading = this._locationCommanService.calculateHeading(
        currentLatLng,
        moveToLatLng
      );
      this.imageRoatedById(this.activeHistoryTrack.markerId, heading);
      //this.activeHistoryTrack.vehicleMarker.setRotation(heading);
      this._moveMarkerService.animatedMoveWithSelf(
        this.activeHistoryTrack.vehicleMarker,
        currentLatLng,
        moveToLatLng,
        this.speed,
        (e) => {
          this.activeHistoryTrack.currentVehicleIndex = index;
          if (this.activeHistoryTrack.currentPath.flag != "stop") {
            if (
              index + 1 >=
              this.activeHistoryTrack.currentPath.dataArrayCoords
            ) {
              this.activeHistoryTrack.currentPath.flag = "init";
              this.activeHistoryTrack.currentVehicleIndex = 0;
            } else {
              this.activeHistoryTrack.currentVehicleIndex = index + 1;
              this.play(index + 1);
            }
          }
        }
      );
    }
  }
  pause() {
    this.isHistoryPlay = false;
    this._moveMarkerService.forceStopMarkerMove = true;
    if (
      this.activeHistoryTrack &&
      this.activeHistoryTrack.currentPath &&
      this.activeHistoryTrack.currentPath.flag
    ) {
      this.activeHistoryTrack.currentPath.flag =
        this.activeHistoryTrack.currentPath.flag == "init" ? "init" : "stop";
    }
  }
  changeSpeed(speed) {
    this.speed = speed;
  }
  getDegree(dest) {
    // var point1 = new google.maps.LatLng(lat1, lng1);
    // var point2 = new google.maps.LatLng(lat2, lng2);
    // return google.maps.geometry.spherical.computeHeading(dest, position);
  }
  removeHistoryPath(isAll, index) {
    this.pause();

    this.removeDataBefore();
    this.resetData();
  }
  resetData() {
    this.activeHistoryTrack = {
      endMarker: "",
      vehicleMarker: "",
      lastTracks: {},
      currentPath: {
        flag: "init",
      },
      historyTracks: [],
      activeTrackIndex: 0,
      currentVehicleIndex: 0,
      getTrack: () => {
        return this.activeHistoryTrack.historyTracks[
          this.activeHistoryTrack.activeTrackIndex
        ];
      },
    };
  }
  removeDataBefore() {
    if (this.historyPathId) {
      this._locationCommanService.removeSourceById(
        this.map,
        this.historyPathId
      );
      this._locationCommanService.removeAllSource(this.map);
    }
    if (this.activeHistoryTrack.vehicleMarker) {
      this.activeHistoryTrack.vehicleMarker.remove();
    }
    if (this.activeHistoryTrack.endMarker) {
      this.activeHistoryTrack.endMarker.remove();
    }
  }
  setStoppagePoints(id, stoppageData) {
    this.stoppagesData.item[id] = stoppageData;
    this.displayStoppage();
  }
  displayStoppage() {
    if (this.historyMode.isParking) {
      this._moveMarkerService.stoppageMarker(
        this.map,
        this.stoppagesData.item[this.uniqueIdForHistory],
        this.stoppagesData
      );
    }
  }
  getAllAddress() {
    this.activeHistoryTrack.currentPath.dataArrayCoords.forEach((item) => {
      item.latLngKey = item.lat + "_" + item.lng;
      this.getAddress(item.lat, item.lng, item.latLngKey);
    });
  }
  getAddress(lat, lng, key) {
    var latlng_1 = {
      lat: lat,
      long: lng,
    };
    if (!this.contactService.localAddress[key]) {
      this.contactService.localAddress[key] = "";
      this.contactService.getAddressByApi(latlng_1).subscribe((res) => {
        if (res.address != undefined) {
          this.contactService.localAddress[key] = res.address;
        }
      });
    } else {
    }
  }

  imageRoatedById(id, degreeList) {
    const rotated = document.getElementById(id);
    if (rotated && degreeList[0]) {
      let degree = degreeList[0];

      rotated.style.transform = `rotate(${degree}deg)`;
    }
  }
}
