// configurations
const mapboxglApiToken = 'pk.eyJ1IjoiaWlyb2thcnBwYW5lbiIsImEiOiJjbGp5N2hjNnEwMjJrM2NwaDlqb2I1NzdtIn0.OCHoNmXCEDpJnu53S5SHYA';
const mapboxglCustomTheme = 'mapbox://styles/iirokarppanen/clkmn36ts001q01qx71oycubk';
const defaultLongitude = 24.825637;
const defaultLatitude = 60.185934;
const defaultZoom = 14;

let map;
let currentMarkers = [];

function closeMap(){

  // Remove popups
  Array.from(document.getElementById("map_container").childNodes).forEach(node => node.remove());
  // Destroy map instance and hide map settings
  map.remove();
  map_container.classList.replace("map_container", "map_container_hidden");
  if(settings.className === "settings"){
    settings.classList.replace("settings", "settings-minimized");
  }
  document.getElementById("toggleSettings").style.display = "none";
  // Display open map button
  document.getElementById("mapButton").classList.replace("mapButtonHidden", "mapButton");

  // Display video feeds
  document.getElementById("cameras").classList.replace("cameras-hidden", "cameras");

  // Give video canvases correct name
  Array.from(document.getElementsByClassName("camera-canvas")).forEach(canvas => canvas.setAttribute('name', selectedDevice));

}

function openMap(){
  // Disable camera canvases before loading map by removing their name
  let canvases = document.getElementsByClassName("camera-canvas");
  Array.from(canvases).forEach((canvas) => canvas.setAttribute("name", ""));

  // Hide camera container
  document.getElementById("cameras").classList.replace("cameras", "cameras-hidden");

  // Close device panel to load map on whole screen
  if(devices.className === "devices"){
    devices.classList.replace("devices", "devices-minimized");
    togglePanelIcon.classList.replace("togglePanelIcon", "togglePanelIconClosed");
  }

  // Disable buttons during map load
  document.getElementById("togglePanel").setAttribute('disabled', '');
  document.getElementById("mapButton").setAttribute('disabled', '');

  // Display loading spinner
  loading.style.display = "flex";
  
  // Load map theme from localstorage or use default
  let mapTheme = localStorage.getItem("theme") || mapboxglCustomTheme
  
  // Initialize map
  mapboxgl.accessToken = mapboxglApiToken;
  map = new mapboxgl.Map({
    container: 'map_container', 
    style: mapTheme,
    center: [defaultLongitude, defaultLatitude], 
    zoom: defaultZoom
  });

  map.on('load', function() {      
    map_container.classList.replace("map_container_hidden", "map_container");
    loading.style.display = "none";
    document.getElementById("togglePanel").removeAttribute("disabled");
    document.getElementById("mapButton").removeAttribute("disabled");
    document.getElementById("mapButton").classList.remove("mapButton");
    document.getElementById("mapButton").classList.add("mapButtonHidden");
    document.getElementById("toggleSettings").style.display = "block";
    map.resize();
    handleCheckBoxes();
  });

  // add buildings to map
  map.on('style.load', () => {
    const layers = map.getStyle().layers;
    const labelLayerId = layers.find(
      (layer) => layer.type === 'symbol' && layer.layout['text-field']
    ).id;
      
    map.addLayer(buildings, labelLayerId);
  });
}
  
// Map Settings
function toggleSettings(){
  handleCheckBoxes();
  settings.className === "settings-minimized" ? 
  settings.className = "settings" :
  settings.className = "settings-minimized"
}

function switchTheme(theme){
  map.setStyle(theme); 
  localStorage.setItem("theme", theme);

  // Reset settings on theme change
  localStorage.setItem("locationLabel", "visible")
  localStorage.setItem("streetLabel", "visible")
  localStorage.setItem("streetHighlight", "visible")
  localStorage.setItem("buildings", "visible")
  handleCheckBoxes();

  // On mobile close settings panel so users can see the change immediately
  if(window.screen.width < 800){
    toggleSettings();
  }
}

function toggleOption(type, checked){
  localStorage.setItem(type, checked ? "visible" : "hidden");
  const newProperty = checked ? "visible" : "none";

  if(type === "locationLabel"){
    map.style.stylesheet.layers.forEach(function(layer) {
      if(layer.id.includes("label") && !layer.id.includes("road")) {
        map.setLayoutProperty(layer.id,"visibility", newProperty);
      }
    });
  }
  if(type === "streetLabel"){
    map.style.stylesheet.layers.forEach(function(layer) {
      if(layer.id.includes("label") && layer.id.includes("road")) {
        map.setLayoutProperty(layer.id,"visibility", newProperty);
      }
    });
  }
  if(type === "streetHighlight"){
    map.style.stylesheet.layers.forEach(function(layer) {
      if(layer.type === "line" && (layer.id.includes("road") || layer.id.includes("tunnel") || layer.id.includes("bridge"))) {
        map.setLayoutProperty(layer.id,"visibility", newProperty);
      }
    });
  }
  if(type === "buildings"){
    map.getStyle().layers.forEach(function(layer) {
      if (layer.id === "add-3d-buildings") {
        map.setLayoutProperty(layer.id,"visibility", newProperty);
      }
    });
  }
}

function handleCheckBoxes(){
  const options = ["locationLabel", "streetLabel", "streetHighlight", "buildings"];

  for(let option of options) {
    let checkBox = document.getElementById(option);

    if(localStorage.getItem(option) !== null){
      checkBox.checked = (localStorage.getItem(option) === "visible");
      toggleOption(option, checkBox.checked);
    }
  }
}

function updateMap(gpsData){
  // Don't update markers when map not visible
  if(document.getElementById("map_container").className.includes("hidden")){
    return;
  }

  // Remove markers after 10 seconds to get rid of the ones no longer in gps data
  for(let marker of currentMarkers){
    let difference = (new Date().getTime()) - (marker.getElement().creationTime).getTime();
    if(((difference / 1000) > 10) && marker.getElement().id !== selectedDevice){
      marker.getElement().remove();
      currentMarkers = currentMarkers.filter(obj => obj !== marker);
    }
  }

  // Create new marker or update coordinates
  for(let device of gpsData){
    const existingMarker = currentMarkers.find(obj => (obj._element.id).includes(device.name));
    if(existingMarker){
      existingMarker.setLngLat(device.coordinates);
    }
    else{
      const markerDiv = document.createElement('div');
      markerDiv.className = device.name == "Live Demo" ? "marker-demo" : "marker";
      markerDiv.id = device.name;
      markerDiv.creationTime = new Date();
      markerDiv.innerHTML = `<p id="${device.name}" class="marker-name">${device.name}</p>`;

      const marker = new mapboxgl.Marker(markerDiv)
        .setLngLat(device.coordinates)
        .addTo(map);
        
      currentMarkers.push(marker);

      const popup = new mapboxgl.Popup({offset: [-140, -200]}).setHTML(
        `<div id="${device.name}" onclick="closeMap();selectedDevice=id;">
          <h2>${device.name}</h2>
          <canvas class="camera-canvas" id="thermal_canvas" name="${device.name}"></canvas>
          <canvas class="camera-canvas" id="hd_canvas" name="${device.name}"></canvas>
        </div>`
      );
      markerDiv.addEventListener('click', () => {
        closeMap();
      })
      markerDiv.addEventListener('mouseenter', () => {
        selectedDevice = device.name;

        // DON'T CHANGE THIS
        if(marker._popup === null){
          Array.from(document.getElementsByClassName("mapboxgl-popup")).forEach(e => e.remove());
          marker.setPopup(popup);
          marker.togglePopup();
        }
        else{
          currentMarkers.forEach((currentMarker) => {
            if(currentMarker._element.id !== selectedDevice){
              try{currentMarker._popup.remove()}catch{}
            }
          })
          if(marker._popup._container === undefined){
          marker.togglePopup();
          }
        }
        }
      );
    }
  }
}


const buildings = {
  'id': 'add-3d-buildings',
  'source': 'composite',
  'source-layer': 'building',
  'filter': ['==', 'extrude', 'true'],
  'type': 'fill-extrusion',
  'minzoom': 15,
  'paint': {
    'fill-extrusion-color': '#aaa',
    'fill-extrusion-height': [
      'interpolate',
      ['linear'],
      ['zoom'],
      15,
      0,
      15.05,
      ['get', 'height']
    ],
    'fill-extrusion-base': [
      'interpolate',
      ['linear'],
      ['zoom'],
      15,
      0,
      15.05,
      ['get', 'min_height']
    ],
    'fill-extrusion-opacity': 0.8
  }
};