import React, { useState, useEffect } from "react";
import { fromJS, Map } from "immutable";
import MAP_STYLE from "./map-style-basic-v8.json";

const defaultMapStyle: Map<string, any> = fromJS(MAP_STYLE);
const defaultLayers = defaultMapStyle.get("layers");

const categories: string[] = [
  "labels",
  "roads",
  "buildings",
  "parks",
  "water",
  "background",
];

// Layer id patterns by category
const layerSelector: { [key: string]: RegExp } = {
  background: /background/,
  water: /water/,
  parks: /park/,
  buildings: /building/,
  roads: /bridge|road|tunnel/,
  labels: /label|place|poi/,
};

// Layer color class by type
const colorClass: { [key: string]: string } = {
  line: "line-color",
  fill: "fill-color",
  background: "background-color",
  symbol: "text-color",
};

function getMapStyle({ visibility, color }: MapStyleOptions): Map<string, any> {
  const layers = defaultLayers
    .filter((layer: any) => {
      const id = layer.get("id");
      return categories.every(
        (name) => visibility[name] || !layerSelector[name].test(id)
      );
    })
    .map((layer: any) => {
      const id = layer.get("id");
      const type = layer.get("type");
      const category = categories.find((name) => layerSelector[name].test(id));
      if (category && colorClass[type]) {
        return layer.setIn(["paint", colorClass[type]], color[category]);
      }
      return layer;
    });

  return defaultMapStyle.set("layers", layers);
}

interface MapStyleOptions {
  visibility: { [key: string]: boolean };
  color: { [key: string]: string };
}

interface StyleControlsProps {
  onChange: (style: Map<string, any>) => void;
}

function StyleControls(props: StyleControlsProps) {
  const [visibility, setVisibility] = useState<any>({
    water: true,
    parks: true,
    buildings: true,
    roads: true,
    labels: true,
    background: true,
  });

  const [color, setColor] = useState<any>({
    water: "#DBE2E6",
    parks: "#E6EAE9",
    buildings: "#c0c0c8",
    roads: "#ffffff",
    labels: "#78888a",
    background: "#EBF0F0",
  });

  useEffect(() => {
    props.onChange(getMapStyle({ visibility, color }));
  }, [visibility, color]);

  const onColorChange = (name: string, value: string) => {
    setColor({ ...color, [name]: value });
  };

  const onVisibilityChange = (name: string, value: boolean) => {
    setVisibility({ ...visibility, [name]: value });
  };

  return (
    <div className="control-panel">
      <h3>Dynamic Styling</h3>
      <hr />
      {categories.map((name) => (
        <div
          key={name}
          className="input"
          style={{
            display: "flex",
            flexDirection: "row",
            justifyContent: "space-between",
            alignItems: "center",
          }}
        >
          <label>{name}</label>
          <input
            type="checkbox"
            checked={visibility[name]}
            onChange={(evt) => onVisibilityChange(name, evt.target.checked)}
          />
          <input
            type="color"
            value={color[name]}
            disabled={!visibility[name]}
            onChange={(evt) => onColorChange(name, evt.target.value)}
          />
        </div>
      ))}
    </div>
  );
}

export default React.memo(StyleControls);
