import { Dialog, Disclosure, Menu, Transition } from "@headlessui/react";
import {
  ChevronDownIcon,
  ChevronUpIcon,
} from "@heroicons/react/20/solid";
import { XMarkIcon } from "@heroicons/react/24/outline";
import { Fragment, useRef, useState } from "react";

import Map, { Layer, Popup, ScaleControl, Source } from "react-map-gl/maplibre";
import basemap from "./assets/basemap.json";
import mapstyle from "./countries.json";


mapstyle.sources.remap.url = import.meta.env.MODE === "localhost" ? "http://localhost:8080/capabilities/remap.json" : mapstyle.sources.remap.url

const paintedLayers = mapstyle.layers.reduce((acc, cur) => ({ ...acc, [cur.id]: cur }), {})
const toggleLayers = ["Подложка"]


const initialPaintFilters = [
  {
    id: "parameter_name",
    name: "Показатель ВИЭ-генерации",
    options: [
      {
        "value": "power_fact_mw",
        "label": "Фактическая установленная мощность, МВт",
        "checked": true
      },
      {
        "value": "generation_gwh",
        "label": "Производство электроэнергии, млн кВт⋅ч",
        "checked": false
      },
      {
        "value": "res_share_generation",
        "label": "Доля в выработке электроэнергии, %",
        "checked": false
      },
      {
        "value": "res_share_power",
        "label": "Доля в балансе мощности, %",
        "checked": false
      },
      {
        "value": "generation_to_population_kWh_pers",
        "label": "Производство электроэнергии на душу населения, кВт⋅ч/чел.",
        "checked": false
      }
    ]
  },
]

const initialFilterFilters = [
  {
    id: "id_tech",
    name: "ВИЭ-технология",
    options: [
      {
        "value": 1,
        "label": "СЭС",
        "checked": false
      },
      {
        "value": 2,
        "label": "Наземные ВЭС",
        "checked": false
      },
      {
        "value": 3,
        "label": "Офшорные ВЭС",
        "checked": false
      },
      {
        "value": 4,
        "label": "ГЭС",
        "checked": false
      },
      {
        "value": 5,
        "label": "БиоЭС",
        "checked": false
      },
      {
        "value": 6,
        "label": "ГеоЭС",
        "checked": false
      },
      {
        "value": 8,
        "label": "СЭС и ВЭС",
        "checked": false
      },
      {
        "value": 7,
        "label": "Все ВИЭ",
        "checked": true
      }
    ]
  },
  {
    "id": "year",
    "name": "Год",
    "options": [
      {
        "value": 2010,
        "label": 2010,
        "checked": false
      },
      {
        "value": 2011,
        "label": 2011,
        "checked": false
      },
      {
        "value": 2012,
        "label": 2012,
        "checked": false
      },
      {
        "value": 2013,
        "label": 2013,
        "checked": false
      },
      {
        "value": 2014,
        "label": 2014,
        "checked": false
      },
      {
        "value": 2015,
        "label": 2015,
        "checked": false
      },
      {
        "value": 2016,
        "label": 2016,
        "checked": false
      },
      {
        "value": 2017,
        "label": 2017,
        "checked": false
      },
      {
        "value": 2018,
        "label": 2018,
        "checked": false
      },
      {
        "value": 2019,
        "label": 2019,
        "checked": false
      },
      {
        "value": 2020,
        "label": 2020,
        "checked": false
      },
      {
        "value": 2021,
        "label": 2021,
        "checked": false
      },
	  {
        "value": 2022,
        "label": 2022,
        "checked": false
      },
      {
        "value": 2023,
        "label": 2023,
        "checked": false
      },
      {
        "value": 2024,
        "label": 2024,
        "checked": true
      }
    ]
  }
]

export default function Countries({ mapOptions, onMapOptionClick }) {
  const mapRef = useRef(null);

  const [open, setOpen] = useState(false)

  const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);

  const [popupInfo, setPopupInfo] = useState(null);

  const [paintFilters, setPaintFilters] = useState(initialPaintFilters);
  const [filterFilters, setFilterFilters] = useState(initialFilterFilters);


  const generatePopup = (info) => {
    // console.log(info)
    const [currentTech, currentYear, currentParameter] = filterFilters.map(f => f.options.find(o => o.checked)).concat(paintFilters[0].options.find(o => o.checked))
    return (
      <div>
        <img src={`/flags/${info.id_country}.png`} className="mb-4 w-36 outline outline-gray-400" />
        {info.area_km2 && <p className="text-gray-500">Площадь <span className="text-gray-900 font-medium">{(info.area_km2 / 1000).toFixed(1).replace(".", ",")} тыс. км²</span></p>}
        {info.population_person && <p className="text-gray-500">Численность населения <span className="text-gray-900 font-medium">{(info.population_person / 1000).toFixed(1).replace(".", ",")} тыс. чел.</span></p>}
        {info.population_densitiy_pers_km2 && <p className="text-gray-500">Плотность населения <span className="text-gray-900 font-medium">{info.population_densitiy_pers_km2.toFixed(1).replace(".", ",")} чел./км²</span></p>}
        {info.year_carbon_neutrality && <p className="text-gray-500">Целевой год достижения углеродной нейтральности <span className="text-gray-900 font-medium">{info.year_carbon_neutrality}</span></p>}

        {info[currentParameter.value] &&
          <div className="relative overflow-x-auto py-6">
            <p className="text-sm font-medium">{currentParameter.label} в {currentYear.label} году</p>
            <table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
              <tbody>
                {info[currentParameter.value] != null &&
                  <tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
                    <th scope="row" className="px-2 py-4 font-normal text-gray-900 dark:text-white">
                      {currentTech.label}
                    </th>
                    <td className="px-2 py-4 text-right">
                      {info[currentParameter.value].toFixed(2).replace(".", ",")}
                    </td>
                  </tr>
                }
              </tbody>
            </table>
          </div>
        }


        <div className="relative overflow-x-auto pt-2">
          <p className="text-sm font-medium">Совокупная установленная мощность ВИЭ по итогам {info.static_date_power} года, МВт</p>
          <table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
            <tbody>
              {info.static_power_fact_solar_mw != null &&
                <tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
                  <th scope="row" className="px-2 py-4 font-normal text-gray-900 dark:text-white">
                    Солнечные электростанции
                  </th>
                  <td className="px-2 py-4 text-right">
                    {info.static_power_fact_solar_mw.toFixed(2).replace(".", ",")}
                  </td>
                </tr>
              }
              {info.static_power_fact_onshore_mw != null &&
                <tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
                  <th scope="row" className="px-2 py-4 font-normal text-gray-900 dark:text-white">
                    Наземные ветроэлектростанции
                  </th>
                  <td className="px-2 py-4 text-right">
                    {info.static_power_fact_onshore_mw.toFixed(2).replace(".", ",")}
                  </td>
                </tr>
              }
              {info.static_power_fact_offshore_mw != null &&
                <tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
                  <th scope="row" className="px-2 py-4 font-normal text-gray-900 dark:text-white">
                    Офшорные ветроэлектростанции
                  </th>
                  <td className="px-2 py-4 text-right">
                    {info.static_power_fact_offshore_mw.toFixed(2).replace(".", ",")}
                  </td>
                </tr>
              }
              {info.static_power_fact_res_mw != null &&
                <tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
                  <th scope="row" className="px-2 py-4 font-medium text-gray-900 dark:text-white uppercase">
                    Всего ВИЭ <span className="font-normal normal-case">(включая СЭС, ВЭС, ГЭС, БиоЭС, ГеоЭС)</span>
                  </th>
                  <td className="px-2 py-4 text-right">
                    {info.static_power_fact_res_mw.toFixed(2).replace(".", ",")}
                  </td>
                </tr>
              }
              {info.static_res_share_power != null &&
                <tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
                  <th scope="row" className="px-2 py-4 font-normal text-gray-900 dark:text-white">
                    Доля всей ВИЭ-генерации в балансе мощности страны, %
                  </th>
                  <td className="px-2 py-4 text-right">
                    {info.static_res_share_power.toFixed(2).replace(".", ",")}
                  </td>
                </tr>
              }
              {info.static_solar_wind_share_power != null &&
                <tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
                  <th scope="row" className="px-2 py-4 font-normal text-gray-900 dark:text-white">
                    Доля СЭС и ВЭС в балансе мощности страны, %
                  </th>
                  <td className="px-2 py-4 text-right">
                    {info.static_solar_wind_share_power.toFixed(2).replace(".", ",")}
                  </td>
                </tr>
              }
            </tbody>
          </table>
        </div>

        <p className="text-sm text-gray-400">Источник: IRENA</p>
        {info.date_actualization && <p className="text-sm mt-4 text-gray-600">Дата актуализации: {info.date_actualization}</p>}
      </div>
    )
  }

  const generateLegend = function (parameter) {
    const colors_and_breaks = mapstyle.layers.find(layer => layer.id == parameter.value).paint["fill-color"].slice(2)
    const colors = colors_and_breaks.filter((cb, i) => i % 2 == 0)
    const breaks = colors_and_breaks.filter((cb, i) => i % 2 == 1)
    const labels = [`менее ${breaks[0]}`, ...breaks.map((brk, i, arr) => typeof arr[i + 1] !== 'undefined' ? `${brk} - ${arr[i + 1]}` : `более ${breaks.at(-1)}`)]
    const legend_items = colors.map((col, i) => (
      {
        "color": col,
        "label": labels[i]
      }
    )).reverse()
    return (
      <div>
        <p>{parameter.label}</p>
        {legend_items.map(item => <div className="flex items-center mt-3" key={item.color}><div className={"w-5 h-5 rounded-sm"} style={{ backgroundColor: item.color }}></div><p className="ml-3 text-sm text-gray-600">{item.label}</p></div>)}
      </div>
    )
  }

  const handleFilterToggle = function (event) {

    if (paintFilters.filter((filter) => filter.id == event.target.name).length > 0) {
      const newStatePaintFilters = paintFilters.map((filter) =>
        filter.id == event.target.name
          ? {
            ...filter,
            options: filter.options.map((option) =>
              option.value == event.target.defaultValue
                ? { ...option, checked: true }
                : { ...option, checked: false }
            ),
          }
          : filter
      );
      setPaintFilters(newStatePaintFilters);
    } else {
      const newStateFilterFilters = filterFilters.map((filter) =>
        filter.id == event.target.name
          ? {
            ...filter,
            options: filter.options.map((option) =>
              option.value == event.target.defaultValue
                ? { ...option, checked: true }
                : { ...option, checked: false }
            ),
          }
          : filter
      );
      setFilterFilters(newStateFilterFilters);
    }
  };

  const applyPaintFilters = (filtersObj) => {
    const parameter = filtersObj.find(filter => filter.id == "parameter_name").options.find(option => option.checked).value
    const newPaint = paintedLayers[parameter].paint
    return newPaint
  };

  const applyFilterFilters = (filtersObj) => {
    const year_value = filtersObj.find(f => f.id == "year").options.find(option => option.checked).value
    const tech_value = filtersObj.find(f => f.id == "id_tech").options.find(option => option.checked).value
    return ["all", ["==", ["get", "year"], year_value], ["==", ["get", "id_tech_global"], tech_value]]
  };



  const handleClick = (event) => {
    if (event.features[0]) {
      event.originalEvent.stopPropagation();
      setPopupInfo({
        lon: event.lngLat.lng,
        lat: event.lngLat.lat,
        ...event.features[0].properties
      })
      setOpen(true)
    }
  };

  const handleMouseEnter = (event) => {
    const feature = event.features[0];
    if (!feature) return;

    mapRef.current.getCanvas().style.cursor = "pointer";
  };

  const handleMouseLeave = (event) => {
    const feature = event.features[0];
    if (!feature) {
      return;
    }
    mapRef.current.getCanvas().style.cursor = "";
  };

  return (
    <div className="bg-white">
      <div>
        <main className="mx-auto px-4 sm:px-6 lg:px-8">
          <div className="flex items-baseline justify-between border-b border-gray-200 pt-24 pb-6">
            <h1 className="text-4xl font-bold tracking-tight text-gray-900">
              Развитие возобновляемой энергетики в странах мира
            </h1>
            <div className="flex items-center">
              <Menu as="div" className="relative inline-block text-left">
                <div>
                  <Menu.Button className="hidden group inline-flex justify-center text-sm font-medium text-gray-700 hover:text-gray-900">
                    {mapOptions.find((option) => option.current).name}
                    <ChevronDownIcon
                      className="-mr-1 ml-1 h-5 w-5 flex-shrink-0 text-gray-400 group-hover:text-gray-500"
                      aria-hidden="true"
                    />
                  </Menu.Button>
                </div>

                <Transition
                  as={Fragment}
                  enter="transition ease-out duration-100"
                  enterFrom="transform opacity-0 scale-95"
                  enterTo="transform opacity-100 scale-100"
                  leave="transition ease-in duration-75"
                  leaveFrom="transform opacity-100 scale-100"
                  leaveTo="transform opacity-0 scale-95"
                  show={true}
                >
                  <Menu.Items className="absolute right-0 z-10 mt-2 w-40 origin-top-right rounded-md bg-white shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none">
                    <div className="py-1">
                      {mapOptions.map((option) => (
                        <Menu.Item key={option.name}>
                          <a
                            href="#"
                            className={option.current ? 'font-medium text-gray-900 block px-4 py-2 text-sm' : 'text-gray-500 block px-4 py-2 text-sm'}
                            onClick={onMapOptionClick}
                          >
                            {option.name}
                          </a>
                        </Menu.Item>
                      ))}
                    </div>
                  </Menu.Items>
                </Transition>
              </Menu>
            </div>
          </div>

          <section aria-labelledby="products-heading" className="pt-6 pb-24">
            <div className="grid grid-cols-1 gap-x-8 gap-y-10 md:grid-cols-4">

              <form className="hidden md:block h-[65vh] px-1 py-1 overflow-y-scroll">
                {/* Layers */}
                <ul
                  role="list"
                  className="space-y-4 border-b border-gray-200 pb-6 text-sm font-medium text-gray-900"
                >
                  {toggleLayers.map((layer_name) => (
                    <div key={layer_name} className="flex items-center">
                      <input
                        id={layer_name}
                        name={layer_name}
                        defaultValue={layer_name}
                        type="checkbox"
                        defaultChecked={true}
                        className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
                        onChange={(event) => {
                          mapRef.current
                            .getMap()
                            .setLayoutProperty(
                              event.target.id,
                              "visibility",
                              event.target.checked ? "visible" : "none"
                            );
                        }}
                      />
                      <label
                        htmlFor={layer_name}
                        className="ml-3 text-sm text-gray-600"
                      >
                        {layer_name}
                      </label>
                    </div>
                  ))}
                </ul>

                {/* Legend */}
                <Disclosure as="div" className="border-b border-gray-200 py-6">
                  {({ open }) => (
                    <>
                      <h3 className="-my-3 flow-root">
                        <Disclosure.Button className="flex w-full items-center justify-between bg-white py-3 text-sm text-gray-400 hover:text-gray-500">
                          <span className="font-medium text-gray-900">
                            Легенда
                          </span>
                          <span className="ml-6 flex items-center">
                            {open ? (
                              <ChevronUpIcon
                                className="h-5 w-5"
                                aria-hidden="true"
                              />
                            ) : (
                              <ChevronDownIcon
                                className="h-5 w-5"
                                aria-hidden="true"
                              />
                            )}
                          </span>
                        </Disclosure.Button>
                      </h3>
                      <Disclosure.Panel className="pt-6">
                        <div className="space-y-4">
                          {generateLegend(paintFilters.find(f => f.id == "parameter_name").options.find(parameter => parameter.checked))}
                        </div>
                      </Disclosure.Panel>
                    </>
                  )}
                </Disclosure>

                {/* Filters */}
                {paintFilters.concat(filterFilters).map((section) => (
                  <Disclosure
                    as="div"
                    key={section.id}
                    className="border-b border-gray-200 py-6"
                  >
                    {({ open }) => (
                      <>
                        <h3 className="-my-3 flow-root">
                          <Disclosure.Button className="flex w-full items-center justify-between bg-white py-3 text-sm text-gray-400 hover:text-gray-500">
                            <span className="font-medium text-gray-900">
                              {section.name}
                            </span>
                            <span className="ml-6 flex items-center">
                              {open ? (
                                <ChevronUpIcon
                                  className="h-5 w-5"
                                  aria-hidden="true"
                                />
                              ) : (
                                <ChevronDownIcon
                                  className="h-5 w-5"
                                  aria-hidden="true"
                                />
                              )}
                            </span>
                          </Disclosure.Button>
                        </h3>
                        <Disclosure.Panel className="pt-6">
                          <div className="space-y-4">
                            {section.options.map((option, optionIdx) => (
                              <div
                                key={option.value}
                                className="flex items-center"
                              >
                                <input
                                  id={`filter-${section.id}-${optionIdx}`}
                                  name={`${section.id}`}
                                  defaultValue={option.value}
                                  type="radio"
                                  defaultChecked={option.checked}
                                  className="peer h-4 w-4 rounded-full border-gray-400 text-indigo-600 focus:ring-indigo-500 disabled:text-gray-400 disabled:border-gray-200"
                                  onChange={handleFilterToggle}
                                  disabled={
                                    (paintFilters[0].options.find(o => o.checked).value == "res_share_generation" ||
                                    paintFilters[0].options.find(o => o.checked).value == "res_share_power" ||
                                    paintFilters[0].options.find(o => o.checked).value == "generation_to_population_kWh_pers") &&
                                    section.id == "id_tech" && option.value < 7 ?
                                    true
                                    : false
                                  }
                                />
                                <label
                                  htmlFor={`filter-${section.id}-${optionIdx}`}
                                  className="ml-3 text-sm text-gray-600 peer-disabled:text-gray-300"
                                >
                                  {option.label}
                                </label>
                              </div>
                            ))}
                          </div>
                        </Disclosure.Panel>
                      </>
                    )}
                  </Disclosure>
                ))}


                {/* Metadata */}
                <Disclosure as="div" className="border-b border-gray-200 py-6">
                  {({ open }) => (
                    <>
                      <h3 className="-my-3 flow-root">
                        <Disclosure.Button className="flex w-full items-center justify-between bg-white py-3 text-sm text-gray-400 hover:text-gray-500">
                          <span className="font-medium text-gray-900">
                            Метаданные
                          </span>
                          <span className="ml-6 flex items-center">
                            {open ? (
                              <ChevronUpIcon
                                className="h-5 w-5"
                                aria-hidden="true"
                              />
                            ) : (
                              <ChevronDownIcon
                                className="h-5 w-5"
                                aria-hidden="true"
                              />
                            )}
                          </span>
                        </Disclosure.Button>
                      </h3>
                      <Disclosure.Panel className="pt-6">
                        <div className="space-y-4">
                          <p className="text-sm">
                            Границы показаны по состоянию на 2021 год
                          </p>
                          <p className="text-sm">
                            &copy; Ассоциация развития возобновляемой энергетики
                          </p>
                        </div>
                      </Disclosure.Panel>
                    </>
                  )}
                </Disclosure>
              </form>

              {/* Map itself */}
              <div className="md:col-span-3">
                <div className="h-[65vh]">
                  <Map
                    initialViewState={{
                      latitude: mapstyle.center[0],
                      longitude: mapstyle.center[1],
                      zoom: mapstyle.zoom,
                    }}
                    mapStyle={basemap}
                    minZoom={mapstyle.minZoom}
                    ref={mapRef}
                    interactiveLayerIds={["power_fact_mw"]}
                    onClick={handleClick}
                    onMouseEnter={handleMouseEnter}
                    onMouseLeave={handleMouseLeave}
                    maxZoom={6}
                    hash
                  >

                    {open && <Popup
                      longitude={popupInfo.lon}
                      latitude={popupInfo.lat}
                      closeButton={false}
                    >
                      {popupInfo.country_russian_name}
                    </Popup>}
                    <ScaleControl />
                    <Source
                      id="remap"
                      {...mapstyle.sources.remap}
                    >
                      <Layer {...paintedLayers["power_fact_mw"]} paint={applyPaintFilters(paintFilters)} filter={applyFilterFilters(filterFilters)} />
                      <Layer {...paintedLayers["Границы"]} />
                    </Source>
                  </Map>
                </div>
              </div>
            </div>
          </section>
        </main>
        <Transition.Root show={open} as={Fragment}>
          <Dialog as="div" className="relative z-10" onClose={setOpen}>
            <Transition.Child
              as={Fragment}
              enter="ease-in-out duration-500"
              enterFrom="opacity-0"
              enterTo="opacity-100"
              leave="ease-in-out duration-500"
              leaveFrom="opacity-100"
              leaveTo="opacity-0"
            >
              <div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
            </Transition.Child>

            <div className="fixed inset-0 overflow-hidden">
              <div className="absolute inset-0 overflow-hidden">
                <div className="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10">
                  <Transition.Child
                    as={Fragment}
                    enter="transform transition ease-in-out duration-500 sm:duration-700"
                    enterFrom="translate-x-full"
                    enterTo="translate-x-0"
                    leave="transform transition ease-in-out duration-500 sm:duration-700"
                    leaveFrom="translate-x-0"
                    leaveTo="translate-x-full"
                  >
                    <Dialog.Panel className="pointer-events-auto relative w-screen max-w-md">
                      <Transition.Child
                        as={Fragment}
                        enter="ease-in-out duration-500"
                        enterFrom="opacity-0"
                        enterTo="opacity-100"
                        leave="ease-in-out duration-500"
                        leaveFrom="opacity-100"
                        leaveTo="opacity-0"
                      >
                        <div className="absolute top-0 left-0 -ml-8 flex pt-4 pr-2 sm:-ml-10 sm:pr-4">
                          <button
                            type="button"
                            className="rounded-md text-gray-300 hover:text-white focus:outline-none focus:ring-2 focus:ring-white"
                            onClick={() => setOpen(false)}
                          >
                            <span className="sr-only">Close panel</span>
                            <XMarkIcon className="h-6 w-6" aria-hidden="true" />
                          </button>
                        </div>
                      </Transition.Child>
                      <div className="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl">
                        <div className="px-4 sm:px-6">
                          <Dialog.Title className="text-lg font-medium text-gray-900">{popupInfo && popupInfo.country_russian_name}</Dialog.Title>
                        </div>
                        <div className="relative mt-6 flex-1 px-4 sm:px-6">
                          {/* Replace with your content */}
                          {popupInfo && generatePopup(popupInfo)}
                          {/* /End replace */}
                        </div>
                      </div>
                    </Dialog.Panel>
                  </Transition.Child>
                </div>
              </div>
            </div>
          </Dialog>
        </Transition.Root>
      </div>
    </div>
  );
}
