import type { StyleSpecification, VectorSourceSpecification } from "maplibre-gl";

import { GEOSERVER_WORKSPACE, MAP_URL } from "./geoserver-config";
import { MAP_STYLE_TOKENS } from "./map-colors";
import {
  SCADA_ANALYSIS_SOURCE_ID,
  createEmptyScadaAnalysisCollection
} from "./scada-analysis";

export const WATER_NETWORK_GLOBAL_VIEW = {
  bbox3857: [13508801.930066336, 3608163.3499832638, 13555650.638648884, 3633685.137885742]
} as const;

export const SOURCE_LAYERS = {
  pipes: "geo_pipes_mat",
  junctions: "geo_junctions_mat",
  valves: "geo_valves",
  reservoirs: "geo_reservoirs",
  scada: "geo_scada",
  pumps: "geo_pumps",
  tanks: "geo_tanks"
} as const;

export const WATER_NETWORK_SOURCE_IDS = [
  "pipes",
  "junctions",
  "valves",
  "reservoirs",
  "scada",
  "pumps",
  "tanks"
] as const;

export type WaterNetworkSourceId = (typeof WATER_NETWORK_SOURCE_IDS)[number];

export type SupplyLayerCatalogItem = {
  id: WaterNetworkSourceId;
  sourceLayer: (typeof SOURCE_LAYERS)[WaterNetworkSourceId];
  geometry: "line" | "point";
  available: boolean;
  label: string;
  icon: string;
};

export const SUPPLY_LAYER_CATALOG = [
  {
    id: "pipes",
    sourceLayer: SOURCE_LAYERS.pipes,
    geometry: "line",
    available: true,
    label: "管线",
    icon: "pipe"
  },
  {
    id: "junctions",
    sourceLayer: SOURCE_LAYERS.junctions,
    geometry: "point",
    available: true,
    label: "节点",
    icon: "junction"
  },
  {
    id: "valves",
    sourceLayer: SOURCE_LAYERS.valves,
    geometry: "point",
    available: true,
    label: "阀门",
    icon: "valve"
  },
  {
    id: "reservoirs",
    sourceLayer: SOURCE_LAYERS.reservoirs,
    geometry: "point",
    available: true,
    label: "水库",
    icon: "reservoir"
  },
  {
    id: "scada",
    sourceLayer: SOURCE_LAYERS.scada,
    geometry: "point",
    available: true,
    label: "SCADA",
    icon: "scada-pressure"
  },
  {
    id: "pumps",
    sourceLayer: SOURCE_LAYERS.pumps,
    geometry: "point",
    available: false,
    label: "水泵",
    icon: "pump"
  },
  {
    id: "tanks",
    sourceLayer: SOURCE_LAYERS.tanks,
    geometry: "point",
    available: false,
    label: "水箱",
    icon: "tank"
  }
] as const satisfies readonly SupplyLayerCatalogItem[];

export const AVAILABLE_WATER_NETWORK_SOURCE_IDS = SUPPLY_LAYER_CATALOG.filter(
  (layer) => layer.available
).map((layer) => layer.id) as Extract<
  WaterNetworkSourceId,
  "pipes" | "junctions" | "valves" | "reservoirs" | "scada"
>[];

export type AvailableWaterNetworkSourceId = (typeof AVAILABLE_WATER_NETWORK_SOURCE_IDS)[number];

export function isAvailableWaterNetworkSourceId(
  value: string
): value is AvailableWaterNetworkSourceId {
  return (AVAILABLE_WATER_NETWORK_SOURCE_IDS as readonly string[]).includes(value);
}

export function createWaterNetworkSources() {
  return Object.fromEntries(
    SUPPLY_LAYER_CATALOG.filter((layer) => layer.available).map((layer) => [
      layer.id,
      createGeoServerVectorSource(layer.sourceLayer)
    ])
  ) as Record<AvailableWaterNetworkSourceId, VectorSourceSpecification>;
}

function createGeoServerVectorSource(
  sourceLayer: (typeof SOURCE_LAYERS)[keyof typeof SOURCE_LAYERS]
): VectorSourceSpecification {
  return {
    type: "vector",
    promoteId: "id",
    tiles: [
      `${MAP_URL}/gwc/service/wmts/rest/${GEOSERVER_WORKSPACE}:${sourceLayer}/WebMercatorQuad/{z}/{y}/{x}?format=application/vnd.mapbox-vector-tile`
    ],
    minzoom: 0,
    maxzoom: 24
  };
}

export function createBaseStyle(mapboxToken?: string): StyleSpecification {
  const sources: StyleSpecification["sources"] = {
    [SCADA_ANALYSIS_SOURCE_ID]: {
      type: "geojson",
      data: createEmptyScadaAnalysisCollection()
    }
  };
  const layers: StyleSpecification["layers"] = [
    {
      id: "background",
      type: "background",
      paint: {
        "background-color": MAP_STYLE_TOKENS.canvas.primary
      }
    }
  ];

  if (mapboxToken) {
    sources["mapbox-light"] = {
      type: "raster",
      tiles: [
        `https://api.mapbox.com/styles/v1/mapbox/light-v11/tiles/512/{z}/{x}/{y}@2x?access_token=${mapboxToken}`
      ],
      tileSize: 512,
      attribution:
        '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
    };
    sources["mapbox-satellite"] = {
      type: "raster",
      tiles: [
        `https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v12/tiles/512/{z}/{x}/{y}@2x?access_token=${mapboxToken}`
      ],
      tileSize: 512,
      attribution:
        '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
    };

    layers.push({
      id: "mapbox-light",
      type: "raster",
      source: "mapbox-light",
      paint: {
        "raster-opacity": 0.82,
        "raster-saturation": -0.22,
        "raster-contrast": 0.04
      }
    });
    layers.push({
      id: "mapbox-satellite",
      type: "raster",
      source: "mapbox-satellite",
      layout: {
        visibility: "none"
      },
      paint: {
        "raster-opacity": 0.86,
        "raster-saturation": -0.3,
        "raster-contrast": 0.1
      }
    });
  }

  return {
    version: 8,
    glyphs: "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf",
    sources,
    layers
  };
}
