import Head from 'next/head'
import Link from 'next/link'
import styles from '/styles/Home.module.css'
import { Service, CustomLink, EntryList, ServiceStatus, ServiceType, ServiceLocation } from '../interfaces/LinkTypes'
import Dockerode from 'dockerode';
import { ReactElement, useEffect, useState } from 'react'
import useSWR, { KeyedMutator } from 'swr';

const fetcher = (url: string) => fetch(url).then((res) => res.json())

//function Services(props: EntryList) {
const Services = () => {
  const { serviceList, isLoading, isError } = useServices();

  let content: ReactElement = <></>;

  // TODO: look into asyncing this as well
  useStatus(serviceList);

  if (isError) {
    content = <div className={styles.grid}>Error Loading data</div>
  }
  else if (isLoading) {
    content = <div className={styles.grid}>Loading..</div>
  }
  else if (serviceList) {
    content =
      <div className={styles.grid}>
        {serviceList.map((item: Service) => (
          <Link key={item.name} href={item.href}>
            <a className={styles.contentcard}>
              <div className={styles.contenttitle}><h2>{item.name}</h2></div>
              <div className={item.status === ServiceStatus.online ? styles.contentonline : styles.contentoffline}>{item.status}</div>
              <div><p>{item.desc}</p></div>
              <div className={styles.cardwarn}><p>{item.warn}</p></div>
            </a>
          </Link>
        ))}
      </div>
  }
  return (
    <>
      <Head>
        <title>Neshura Servers</title>
        <meta charSet='utf-8' />
        <link rel="icon" href="/favicon.ico" />
        <meta name="description" content="Lists all available Services, most likely up-to-date" />
      </Head>

      <h1 className={styles.title}>
        Service List
      </h1>

      <p className={styles.description}>
        Lists all available Services, most likely up-to-date
      </p>

      {content}
    </>
  )
}

function useStatus(serviceList: Service[] | undefined) {
  const { data, error } = useSWR('/api/containers', fetcher);

  if (data && serviceList) {
    serviceList.forEach((service: Service) => {
      getStatus(data, service);
    })
  }
  else if (error) {
    console.log(error);
  }
}

function useServices(): { serviceList: Service[] | undefined, isLoading: boolean, isError: boolean } {
  const { data, error } = useSWR('/api/services', fetcher);
  
  return {
    serviceList: data,
    isLoading: !error && !data,
    isError: error
  };
}

function getStatus(containers: Dockerode.ContainerInfo[], entry: Service) {
  // for now only the BRR7-4800U can be used with Docker, needs changing once more Servers are used
  // TODO: support multiple locations for docker
  if (entry.location === ServiceLocation.brr7_4800u) {
    // app in this context means any non-docker page
    if (entry.type === ServiceType.app) {
      fetch(entry.href)
        .then((data: Response) => {
          if (data.ok) {
            if (data.status == 200 || data.status == 301 || data.status == 302) {
              entry.status = ServiceStatus.online;
            }
            else {
              entry.status = ServiceStatus.offline;
            }
          }
          else {
            entry.status = ServiceStatus.offline;
          }
        })
        .catch(error => {
          console.log(error);
          entry.status = ServiceStatus.error;
        });
    }
    else if (entry.type === "docker") {
      entry.status = ServiceStatus.offline;
      // Loop over every found container and compare to the entry provided
      containers.forEach((container: Dockerode.ContainerInfo) => {
        console.log(container)
        if (container.Names.includes("/" + entry.docker_container_name) || container.Names.includes(entry.docker_container_name)) {
          if (container.State === "running") {
            entry.status = ServiceStatus.online;
          }
          else {
            entry.status = ServiceStatus.offline;
          }
        }
        if (entry.docker_container_name == null) {
          console.log("MISSING DOCKER CONTAINER NAME FOR " + entry.name);
          entry.status = ServiceStatus.error;
        }
      });
    }
    else { entry.status = ServiceStatus.error }
  }
  // for non-local locations pinging can be used to see if they're up
  else if (entry.location === ServiceLocation.other) {
    fetch(entry.href)
      .then((data) => {
        if (data.ok) {
          if (data.status == 200 || data.status == 301 || data.status == 302) {
            return (entry.status = ServiceStatus.online);
          }
          else (entry.status = ServiceStatus.offline);
        }
        else {
          entry.status = ServiceStatus.offline;
        }
      })
      .catch((error) => {
        console.log(error);
        entry.status = ServiceStatus.error;
      });
  }
  else { entry.status = ServiceStatus.error }
  return;
}

export default Services