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

type LayerSpecification = StyleSpecification["layers"][number];
type LineLayerSpecification = Extract<LayerSpecification, { type: "line" }>;
type CircleLayerSpecification = Extract<LayerSpecification, { type: "circle" }>;
type SymbolLayerSpecification = Extract<LayerSpecification, { type: "symbol" }>;
type LineWidth = NonNullable<NonNullable<LineLayerSpecification["paint"]>["line-width"]>;
type CircleRadius = NonNullable<NonNullable<CircleLayerSpecification["paint"]>["circle-radius"]>;
type IconSize = NonNullable<NonNullable<SymbolLayerSpecification["layout"]>["icon-size"]>;

export const MAP_MAX_ZOOM = 24;

const lineHitWidth = [
  "interpolate",
  ["linear"],
  ["zoom"],
  11,
  16,
  17,
  18,
  22,
  22,
  24,
  24
] as LineWidth;

const pointHitRadius = [
  "interpolate",
  ["linear"],
  ["zoom"],
  9,
  9,
  12,
  9,
  16,
  10,
  20,
  12,
  24,
  14
] as CircleRadius;

const pipeWidthAtZoom = (
  minor: number,
  medium: number,
  major: number
) => [
  "case",
  [">=", ["to-number", ["coalesce", ["get", "diameter"], 0]], 600],
  major,
  [">=", ["to-number", ["coalesce", ["get", "diameter"], 0]], 300],
  medium,
  minor
] as ExpressionSpecification;

const supplyPipeWidth = [
  "interpolate",
  ["linear"],
  ["zoom"],
  9,
  pipeWidthAtZoom(0.7, 1, 1.4),
  11,
  pipeWidthAtZoom(0.9, 1.3, 1.8),
  14,
  pipeWidthAtZoom(1.2, 1.8, 2.6),
  17,
  pipeWidthAtZoom(1.8, 2.8, 4),
  20,
  pipeWidthAtZoom(2.6, 4.2, 6),
  24,
  pipeWidthAtZoom(3.2, 5.2, 7)
] as unknown as LineWidth;

const supplyPipeCasingWidth = [
  "interpolate",
  ["linear"],
  ["zoom"],
  9,
  pipeWidthAtZoom(2.1, 2.4, 2.8),
  11,
  pipeWidthAtZoom(2.3, 2.7, 3.2),
  14,
  pipeWidthAtZoom(2.7, 3.3, 4.1),
  17,
  pipeWidthAtZoom(3.6, 4.6, 5.8),
  20,
  pipeWidthAtZoom(4.5, 6.1, 7.9),
  24,
  pipeWidthAtZoom(5.2, 7.2, 9)
] as unknown as LineWidth;

const facilityRadius = [
  "interpolate", ["linear"], ["zoom"],
  8.5, 3,
  10, 4.2,
  12, 5.5,
  16, 7,
  20, 9,
  24, 11
] as CircleRadius;

const facilityCasingRadius = [
  "interpolate", ["linear"], ["zoom"],
  8.5, 4,
  10, 5.4,
  12, 7,
  16, 8.5,
  20, 10.5,
  24, 12.5
] as CircleRadius;

const facilityHoverRadius = [
  "interpolate", ["linear"], ["zoom"],
  8.5, 5,
  10, 6.5,
  12, 8,
  16, 9.5,
  20, 11.5,
  24, 13.5
] as CircleRadius;

const facilitySelectedRadius = [
  "interpolate", ["linear"], ["zoom"],
  8.5, 5.5,
  10, 7,
  12, 8.5,
  16, 10,
  20, 12,
  24, 14
] as CircleRadius;

const facilityIconSize = [
  "interpolate", ["linear"], ["zoom"],
  8.5, 0.18,
  10, 0.23,
  12, 0.29,
  16, 0.36,
  20, 0.46,
  24, 0.56
] as IconSize;

export const SUPPLY_LAYER_VISUALS = {
  pipes: {
    minzoom: 8.5,
    casingWidth: supplyPipeCasingWidth,
    width: supplyPipeWidth,
    hoverOutlineWidth: ["interpolate", ["linear"], ["zoom"], 9, 5.5, 13, 8, 17, 12.5, 22, 15, 24, 17] as LineWidth,
    hoverWidth: ["interpolate", ["linear"], ["zoom"], 9, 3, 13, 5.2, 17, 9, 22, 11.5, 24, 13] as LineWidth,
    selectedWidth: ["interpolate", ["linear"], ["zoom"], 9, 4, 13, 6.5, 17, 10.5, 22, 13.5, 24, 16] as LineWidth,
    selectedBorderWidth: ["interpolate", ["linear"], ["zoom"], 9, 1.2, 13, 1.5, 17, 2, 22, 2.5, 24, 3] as LineWidth,
    hitWidth: lineHitWidth
  },
  junctions: {
    minzoom: 15,
    haloRadius: ["interpolate", ["linear"], ["zoom"], 13, 2.8, 17, 6] as CircleRadius,
    haloOpacity: ["interpolate", ["linear"], ["zoom"], 15, 0, 17, 0, 19, 0.55, 24, 0.82] as const,
    radius: ["interpolate", ["linear"], ["zoom"], 13, 1.5, 17, 3.8] as CircleRadius,
    hoverRadius: ["interpolate", ["linear"], ["zoom"], 13, 5, 17, 10] as CircleRadius,
    selectedRadius: ["interpolate", ["linear"], ["zoom"], 13, 5.5, 17, 10.5] as CircleRadius,
    hitRadius: pointHitRadius
  },
  valves: {
    minzoom: 8.5,
    casingWidth: ["interpolate", ["linear"], ["zoom"], 11, 3.2, 17, 7.5, 22, 9, 24, 10] as LineWidth,
    width: ["interpolate", ["linear"], ["zoom"], 11, 1.6, 17, 4.4, 22, 6, 24, 7] as LineWidth,
    haloRadius: facilityCasingRadius,
    radius: facilityRadius,
    hoverOutlineWidth: ["interpolate", ["linear"], ["zoom"], 11, 6, 17, 10.5, 22, 12.5, 24, 14] as LineWidth,
    hoverWidth: ["interpolate", ["linear"], ["zoom"], 11, 4, 17, 7, 22, 9, 24, 10.5] as LineWidth,
    hoverRadius: facilityHoverRadius,
    selectedWidth: ["interpolate", ["linear"], ["zoom"], 11, 5.5, 17, 9, 22, 12, 24, 14] as LineWidth,
    selectedBorderWidth: ["interpolate", ["linear"], ["zoom"], 11, 1.25, 17, 1.75, 22, 2.25, 24, 2.5] as LineWidth,
    selectedRadius: facilitySelectedRadius,
    hitWidth: lineHitWidth,
    hitRadius: pointHitRadius,
    iconSize: facilityIconSize
  },
  reservoirs: {
    minzoom: 8.5,
    haloRadius: ["interpolate", ["linear"], ["zoom"], 8.5, 7, 10, 8.5, 12, 9.5, 16, 11.5, 20, 13.5, 24, 15.5] as CircleRadius,
    radius: ["interpolate", ["linear"], ["zoom"], 8.5, 5.5, 10, 7, 12, 8, 16, 10, 20, 12, 24, 14] as CircleRadius,
    hoverRadius: ["interpolate", ["linear"], ["zoom"], 8.5, 8, 10, 9.5, 12, 10.5, 16, 12.5, 20, 14.5, 24, 16.5] as CircleRadius,
    selectedRadius: ["interpolate", ["linear"], ["zoom"], 8.5, 8.5, 10, 10, 12, 11, 16, 13, 20, 15, 24, 17] as CircleRadius,
    hitRadius: pointHitRadius,
    iconSize: ["interpolate", ["linear"], ["zoom"], 8.5, 0.28, 10, 0.36, 12, 0.42, 16, 0.52, 20, 0.64, 24, 0.76] as IconSize
  },
  scada: {
    minzoom: 8.5,
    haloRadius: ["interpolate", ["linear"], ["zoom"], 8.5, 5.5, 10, 7, 12, 8.5, 16, 10, 20, 12, 24, 14] as CircleRadius,
    radius: ["interpolate", ["linear"], ["zoom"], 8.5, 4, 10, 5.5, 12, 7, 16, 8.5, 20, 10.5, 24, 12.5] as CircleRadius,
    hoverRadius: ["interpolate", ["linear"], ["zoom"], 8.5, 6.5, 10, 8, 12, 9.5, 16, 11, 20, 13, 24, 15] as CircleRadius,
    selectedRadius: ["interpolate", ["linear"], ["zoom"], 8.5, 7, 10, 8.5, 12, 10, 16, 11.5, 20, 13.5, 24, 15.5] as CircleRadius,
    hitRadius: pointHitRadius,
    iconSize: ["interpolate", ["linear"], ["zoom"], 8.5, 0.25, 10, 0.32, 12, 0.4, 16, 0.48, 20, 0.6, 24, 0.72] as IconSize
  },
  pumps: {
    minzoom: 11,
    hoverRadius: 14,
    selectedRadius: 12.5,
    hitRadius: 16,
    iconSize: ["interpolate", ["linear"], ["zoom"], 11, 0.44, 16, 0.66, 20, 0.82, 24, 0.96] as const
  },
  tanks: {
    minzoom: 11,
    hoverRadius: 14,
    selectedRadius: 12.5,
    hitRadius: 16,
    iconSize: ["interpolate", ["linear"], ["zoom"], 11, 0.44, 16, 0.66, 20, 0.82, 24, 0.96] as const
  }
} as const;
