import { Component, signal, OnInit, ChangeDetectorRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LeafletModule } from '@bluehalo/ngx-leaflet';
import { center } from '@turf/turf';
import { Overpass } from '../overpass';
import * as L from 'leaflet';

import * as D from './details';
import * as E from './geojson';

@Component({
  selector: 'app-map',
  imports: [LeafletModule, CommonModule],
  templateUrl: './map.html',
  styleUrl: './map.scss',
})
export class OSMMap implements OnInit {
  private buildingLayer?: L.LayerGroup;

  protected readonly title = signal('HKA-OSM');
  map?: L.Map;
  details?: D.Details;

  osm?: L.TileLayer;
  options: L.MapOptions = {};
  layerControl?: L.Control.Layers;

  isFullscreen = true;

  constructor(
    private overpass: Overpass,
    private cdr: ChangeDetectorRef
  ) {}

  ngOnInit() {
    this.osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      maxNativeZoom: 19,
      maxZoom: 21,
      minZoom: 18,
      attribution: '© OpenStreetMap contributors',
    });

    // Define map options
    this.options = {
      layers: [this.osm],
      zoom: 18, // Zoom level
      center: this.getCenter(), // Center of the map
      maxBounds: L.latLngBounds(
        L.latLng(49.014442, 8.387954), // Southwest corner
        L.latLng(49.017847, 8.395448), // Northeast corner
      ),
      maxBoundsViscosity: 1.0, // Prevent panning outside bounds
    };

    this.layerControl = L.control.layers({
      OpenStreetMap: this.osm,
    });
  }

  onMapReady(map: L.Map) {
    this.map = map;
    this.layerControl?.addTo(this.map);
    this.loadBuildings().addTo(this.map);
    console.log('Map is ready');
  }

  loadBuildings() {
    return L.geoJSON(E.buildings, {
      style: E.buildingSytle,
      onEachFeature: (feature, layer) => {
        layer.on({
          click: (e) => {
            this.isFullscreen = !this.isFullscreen;
            if (!this.isFullscreen) {
              this.map?.setView(this.getCenter(feature.geometry), 20);
              this.buildingLayer = this.queryBuildings(feature.properties.name);
              this.buildingLayer.addTo(this.map!);
              this.details = new D.Details(feature.properties.name, feature.properties.building)
            } else {
              this.map?.setView(this.getCenter(), 18);
              if (this.buildingLayer) {
                this.map?.removeLayer(this.buildingLayer);
              }
            }
            console.log('Set isFullscreen to:', this.isFullscreen);
            console.log('Clicked on feature:', feature.properties?.name);
            this.cdr.detectChanges();
          },
        });
        if (feature.properties && feature.properties.name) {
          layer.bindTooltip(feature.properties.name, {
            permanent: false,
            direction: 'top',
          });
        }
      },
    });
  }

  queryBuildings(building_name: string) {
    // Get the building name from the feature properties and query the Overpass API for detailed building data,
    // including indoor features.

    // Create a new LayerGroup to hold the building polygons
    const resultingLayer = new L.LayerGroup();
    this.overpass.fetchIndoorData(building_name).subscribe((data) => {
      console.log('Fetched building data from Overpass API:', data);

      // Create a mapping of node IDs to their coordinates
      const nodes: Map<number, L.LatLng> = new Map();
      data.elements.forEach((element: any) => {
        if (element.type === 'node') {
          nodes.set(element.id, new L.LatLng(element.lat, element.lon));
        }
      });

      // Process ways and create polygons
      // TODO: Change to features, to also add the meta data of the building, e.g. the name of the room
      data.elements.forEach((element: any) => {
        if (element.type === 'way') {
          const coordinates: L.LatLng[] = [];
          element.nodes.forEach((nodeId: number) => {
            coordinates.push(nodes.get(nodeId)!);
          });
          L.polygon(coordinates, { color: '#999999', fillColor: '#e0e0e0', fillOpacity: 1 }).addTo(
            resultingLayer,
          );
        }
      });
    });
    return resultingLayer;
  }

  private getCenter(feature?: any): L.LatLng {
    // Calculate the center of the feature using Turf.js, or use a default center if no feature is provided.
    let centerPoint: number[] = [];
    if (feature) {
      centerPoint = center(feature).geometry.coordinates.reverse();
    } else {
      centerPoint = [49.015514096207895, 8.391567600294243];
    }
    const result = new L.LatLng(centerPoint[0], centerPoint[1]);
    return result;
  }
}
