import React, {useEffect, useState} from 'react';
import PanelWrapper from "../../meta/PanelWrapper";
import PlanElement from "./components/PlanElement";
import PanelTitle from "../../meta/PanelTitle";
import PanelContent from "../../meta/PanelContent";
import {StationResponse} from "./types/vrrfAPI";
import {Warning} from "phosphor-react";

export type FahrplanPanelDefinition = {
  stops: string[],
  filter: {
    types?: string[],
    destinations?: string[]
  }
}

type Route = {
  uid: string,
  identifier: string,
  heading: string,
  stops: {
    name: string,
    arrival: Date,
    delay?: number
  }[]
}

const FahrplanPanel = (props: {definition: FahrplanPanelDefinition}) => {
  const [routes, setRoutes] = useState<Route[]>([]);

  useEffect(() => {
    const update = async () => {
      const departures = (await Promise.all(props.definition.stops.map(getStopData)))
        .map(d => d.raw)
        .flat();

      let newRoutes: Route[] = [];

      // Determine stop data from the departures
      for(let departure of departures) {
        // First throw away all data that belongs to a filtered category
        if((props.definition.filter.types ?? []).includes(departure.type)) {
          continue;
        }

        // Find existing route with same uid
        const existing_ind = newRoutes.findIndex(r => r.uid === departure.lineref.identifier)

        // Pre-compute values that will be needed regardless
        const delay = stringToDelay(departure.delay);
        const arrival = processArrival(departure.sched_date, departure.time);
        console.log(arrival)

        if(existing_ind === -1) {
          // If it does not exist, create a new route
          newRoutes.push({
            uid: departure.key,
            heading: departure.lineref.direction,
            identifier: departure.line,
            stops: [
              {
                name: departure.internal.stop,
                arrival,
                delay
              }
            ]
          })
        } else {
          // If it doesn't, just add a stop to the existing route
          newRoutes[existing_ind].stops.push({
            name: departure.internal.stop,
            arrival,
            delay: stringToDelay(departure.delay)
          })
        }
      }

      // Sort the output

      // Write to the display
      setRoutes(newRoutes);
    }

    update();
    const interval = setInterval(update, 2 * 60 * 1000);

    return () => {
      clearInterval(interval);
    }
  }, []);

  return (
    <PanelWrapper>
      <PanelTitle title={"ÖPNV Monitor"}/>
      <PanelContent className={"flex flex-col"}>
        <div className={"flex-1 flex flex-col gap-3"}>
          {routes.map((route) => (
            <PlanElement
              key={route.uid}
              tripId={route.uid}
              trainIdentifier={route.identifier}
              trainHeading={route.heading}
              stops={route.stops}
            />
          ))}

          {routes.length === 0 && (
            <div className={"flex-1 flex justify-center items-center"}>
              <div className={"mb-10 flex flex-col items-center"}>
                <Warning size={48} className={"mb-3"}/>
                <p className={"max-w-xs text-center text-zinc-400"}>
                  Aktuell sind keine Abfahrtsdaten verfügbar.
                </p>
              </div>
            </div>
          )}
        </div>
      </PanelContent>
    </PanelWrapper>


  );
};

export default FahrplanPanel;

async function getStopData(stop: string): Promise<StationResponse> {
  const request = await fetch(`https://vrrf.finalrewind.org/${encodeURIComponent(stop)}.json`);
  if(!request.ok) {
    throw new Error("Converting stop did not work");
  }
  const data = await request.json();

  if(data.error) {
    console.warn("Stop data for", stop, "could not be fetched");
  }

  // Add internal reference data
  data.raw = data.raw.map((r: any) => ({
    ...r,
    internal: {
      stop
    }
  }))

  console.log(data);

  return data as StationResponse;
}

function stringToDelay(input: string): number | undefined {
  try {
    const delay = parseInt(input);
    if(delay === 0) {
      return undefined;
    }
    return delay;
  } catch (e) {
    console.warn("While parsing delay, the string was not interpretable", input);
    return undefined;
  }
}

function processArrival(date: string, time: string): Date {
  const d_parts = date.split(".");

  console.log(date, time, "to", `${d_parts[2]}-${d_parts[1]}-${d_parts[0]} ${time}`);
  return new Date(`${d_parts[2]}-${d_parts[1]}-${d_parts[0]} ${time}`);
}

// function sortData(data: any) {
//   for (var i = 0; i < data.length; ++i) {
//     data[i]['stops'] = data[i]['stops'].sort(sortFn);
//     data[i]['timeValue'] = data[i]['stops'][0]['timeValue'];
//   }
//   return data.sort(sortFn);
// }
//
// function sortFn(a: any, b: any) {
//   return a['timeValue'] - b['timeValue'];
// }
//
// function calcDateValue(_year: string, _month: string, _day: string, _hour: string, _minute: string): number {
//   const year = parseInt(_year) * 12 * 31 * 24 * 60;
//   const month = parseInt(_month) * 31 * 24 * 60;
//   const day = parseInt(_day) * 24 * 60;
//   const hour = parseInt(_hour) * 60;
//   const minute = parseInt(_minute);
//   return year+month+day+hour+minute;
// }