import { Router } from "@oak/acorn";
import { db_setup, select_closest } from "./db.ts";
import { DatabaseSync } from "node:sqlite";
import { cors_add, json_mime_add, substitute_base_name_ } from "./utils.ts";
import { assert } from "@std/assert";

import neo4j from "https://deno.land/x/neo4j_driver_lite@5.28.1/mod.ts";
import { graph_setup } from "./graph.ts";

const usingDocker = !Deno.env.has("DISABLE_DOCKER");
const root_url: string = usingDocker
  ? Deno.env.get("ROOT_URL") as string
  : "http://localhost:8080/api";
console.log(`Running in docker configuration? ${usingDocker}`);
assert(root_url, "ROOT_URL env var not defined");

// bind values we're actually using
const substitute_base_name = substitute_base_name_.bind(
  null,
  /\$base_domain/,
  root_url,
);

const { hostname, port } = { hostname: "0.0.0.0", port: 80 };

const neo4jHost = usingDocker ? "neo4j" : "127.0.0.1"; // localhost does NOT work
//const graph_driver = neo4j.driver(
//  `neo4j://${neo4jHost}:7687`,
//  neo4j.auth.basic("neo4j", "your_password"),
//);
//console.log("initializing graph with static data");
//await graph_setup(graph_driver);
//console.log("graph initialization complete");

const db = new DatabaseSync(":memory:");
db_setup(db);

const router = new Router();

const trip_list = (async () => {
  let lst = [];
  // could be a static file but I'm lazy
  for await (const dirEntry of Deno.readDir("trips")) {
    lst.push(dirEntry.name);
  }
  lst = lst.map((name) => URL.parse(root_url + `/trips/${name}`));
  return lst;
})();

router.get(
  "/trips",
  async (_) => {
    const headers = new Headers();
    json_mime_add(headers);
    cors_add(headers);
    return new Response(JSON.stringify(await trip_list), { headers });
  },
);
router.get(
  "/trips/:id",
  async (ctx) => {
    const { params: { id } } = ctx;
    try {
      const bytes = await Deno.readFile(`trips/${id}`);
      const body = substitute_base_name(bytes);
      const headers = new Headers();
      json_mime_add(headers);
      cors_add(headers);

      return new Response(body, { headers });
    } catch (_) {
      return new Response("", { status: 404 });
    }
  },
);

router.get(
  "/stops",
  async (_ctx) => {
    try {
      const bytes = await Deno.readFile(`GET_STOPS.json`);
      const headers = new Headers();
      json_mime_add(headers);
      cors_add(headers);
      return new Response(bytes, { headers });
    } catch (_) {
      return new Response("", { status: 404 });
    }
  },
);
router.get(
  "/stops/:id",
  async (ctx) => {
    const { params: { id } } = ctx;
    try {
      const bytes = await Deno.readFile(`stops/${id}`);
      const body = substitute_base_name(bytes);
      const headers = new Headers();
      json_mime_add(headers);
      cors_add(headers);

      return new Response(body, { headers });
    } catch (_) {
      return new Response("", { status: 404 });
    }
  },
);

const hub =
  (db.prepare("select href from hub_stops where hub='BCT';").get() as {
    href: string;
  }).href;
assert(hub !== undefined, "hub please");
router.get(
  "/path",
  async (ctx) => {
    const query = await ctx.queryParams();
    if (!query) return new Response("no query params", { status: 400 });

    const s_lattitude = query["start_lat"];
    const s_longitude = query["start_lon"];
    const e_lattitude = query["end_lat"];
    const e_longitude = query["end_lon"];
    const _time = query["time"];

    if (
      typeof s_lattitude != "string" || typeof s_longitude != "string" ||
      typeof e_lattitude != "string" || typeof e_longitude != "string" ||
      typeof _time != "string"
    ) {
      return new Response("missing or invalid query params", { status: 400 });
    }

    const start = select_closest(db, {
      lat: Number(s_lattitude),
      lon: Number(s_longitude),
    }, 1);

    const mid = hub;

    const end = select_closest(db, {
      lat: Number(e_lattitude),
      lon: Number(e_longitude),
    }, 1);
    const headers = new Headers();
    json_mime_add(headers);
    cors_add(headers);
    const r = {
      path: [
        {
          trip: {
            href: `${root_url}/trips/BCT_R51_inb_T08`,
            polyline:
              "ivz_GtswmMEQo@P]Ko@_Dg@gByBfCcBjBWX]^Ua@[u@uFdGqErFoDxDiIrIaG|FwGlFyCvCo@r@{@tAq@vAu@vBy@~C_CbJaBhFgF`SY~@YNi@?cDuA_@u@NqAf@{@lAw@vAArBl@jGxB`DlARt@iAnF_BrCi@tBl@Vl@}BEw@p@iAPw@zAaHLYNG|BbArAp@XBNGPOb@{AtAiF@o@s@c@}E}Bg@QS~AzCnALe@X[t@\\r@\\RR?XKr@g@fB_AfDOR[B{@_@aAg@_Bs@_@PWV]FsLeEiCs@eAHaAd@w@xA]jAk@h@uAYKYDs@q@MMCGQ@O?c@_B_@Uj@]P[g@[q@YiAg@sHMmAy@_C}@wCuD{Ja@wA@mAbBkElAyDZuD\\iD^mAh@s@`DcCfBoDzA_DXeBr@iNZoHKkA}@kB{@i@}@QmERmBBw@Om@_@g@c@m@m@Y_AScAImABmAHs@RMFWIc@YIS^H`AGtBVhC^jA|@fAfAj@x@T`JSb@Pn@Zf@bA^tAQjFm@vLQhD]nAoAnCiBhDiDdCk@`ASv@y@fIUzAqBlFmA|BxF`QjHyFo@eAeAqBM{@Hu@Pe@|CaGhCwD\\_@bA}Ah@qAdAiDjAqDtAqDd@q@jAo@~Ce@`DE~CCjAl@hAzBl@pBd@xC@hCY~Co@fBeCrGgB~BcAjA}A|BoErIuBnEm@`Au@b@yANaASuAcA_DbEi@bASzACdBEbDo@pBLT|@b@rKrBbAf@\\^Jp@]~AsFdVqBfI_Kx_@sAlH}@xIk@dHOpCEjCAd@P|IXdLZlDf@tD`DnR\\vCLjDEpFa@~Fs@rI}CrVSdDKhG@pVR|Td@|k@BbQTj@|C~Cl@|DlD|TPjAfBpIp@~EvBhL|BpLxAnIaC|@gE`BL`A`@tB]t@SCaBu@iB{@iDqALhDFzC~Bb@nAg@hCh@p@J",
          },
          enter_bus: {
            href: `${root_url}/stops/BCT_95103`,
            latitude: 42.101991,
            longitude: -75.83611,
            time: "00:00",
          },
          exit_bus: {
            href: `${root_url}/stops/BCT_1`,
            latitude: 42.101354,
            longitude: -75.910801,
            time: "00:00",
          },
        },
        {
          trip: {
            href: `${root_url}/trips/BCT_R28otb_T11`,
            polyline:
              "az}_GvjinM}KiBQsHw@y@oDiEmFeGgFcGyAcB_@c@HcA^qL^gL@w@UyFMcIEkBi@aTi@aREmBCeAi@D_Id@sJl@{GZsRnAw@DASUsLGgBI]MUc@a@UEWBw@Vw@j@y@Nc@FYBj@jFJfAkDx@qAVcA^UFFfCD`AnIc@jH]pIi@rDSzJk@vKo@fDQbF[Di@a@oN_@mNe@eMs@qSW_Ha@{L[}Ie@mL_@mJBoAPyA^iATm@T_@R]l@_@zCgA`@QrBfEVLlATN^D^HPL?XGLQN[CYQQUBS@W@SCoAUSSUc@wAaDkA`@{@^gA`@m@^g@hAa@z@Wv@MrABp@L~FPjDXbI^fLPbEHhDd@tMd@pMj@jNP~GLbFVnK\\pJVfJHpDJrERzGH`FJdENlHN`DCbCUbHEbBQ`GObDGr@|@hA|DlE`F`GvDhE`DnDRrHrDf@Xo@nCl@",
          },
          enter_bus: {
            href: `${root_url}/stops/BCT_2802`,
            latitude: 42.100982,
            longitude: -75.91097,
            time: "00:00",
          },
          exit_bus: {
            href: `${root_url}/stops/BCT_2804`,
            latitude: 42.105488,
            longitude: -75.906281,
            time: "00:00",
          },
        },
      ],
      _legit: [
        start,
        mid,
        end,
      ],
    };
    return new Response(
      JSON.stringify(r),
      { headers },
    );
  },
);

console.log(`Ready! Listening on ${hostname}:${port}`);
router.listen({ hostname, port });
