/* eslint-disable react-x/no-array-index-key */
import {
  mdiHarddisk,
  mdiInformation,
  mdiMemory,
  mdiNetwork,
  mdiPackageVariantClosed,
} from "@mdi/js";
import Icon from "@mdi/react";
import {
  Box,
  LinearProgress,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableRow,
  Typography,
} from "@mui/material";
import Grid from "@mui/material/Grid";
import { PieChart } from "@mui/x-charts";
import { filesize } from "filesize";
import humanizeDuration from "humanize-duration";
import React from "react";
import {
  DiskInfo,
  NetworkInfo,
  ServerApi,
  ServerSystemInfo,
} from "../api/ServerApi";
import { AsyncWidget } from "../widgets/AsyncWidget";
import { VirtWebPaper } from "../widgets/VirtWebPaper";
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";

export function SysInfoRoute(): React.ReactElement {
  const [info, setInfo] = React.useState<ServerSystemInfo>();

  const load = async () => {
    setInfo(await ServerApi.SystemInfo());
  };

  return (
    <AsyncWidget
      load={load}
      loadKey={1}
      build={() => <SysInfoRouteInner info={info!} />}
      errMsg="Failed to load system info"
    />
  );
}

export function SysInfoRouteInner(p: {
  info: ServerSystemInfo;
}): React.ReactElement {
  const sumDiskUsage = p.info.disks.reduce(
    (prev, disk) => {
      return {
        used: prev.used + disk.total_space - disk.available_space,
        free: prev.free + disk.available_space,
      };
    },
    { used: 0, free: 0 }
  );

  return (
    <VirtWebRouteContainer label="Sysinfo">
      <Grid container spacing={2}>
        {/* Memory */}
        <Grid size={{ xs: 4 }}>
          <Box flexGrow={1}>
            <Typography style={{ textAlign: "center" }}>Memory</Typography>
            <PieChart
              series={[
                {
                  data: [
                    {
                      id: 3,
                      value: p.info.system.free_memory,
                      label: "Free",
                    },
                    {
                      id: 2,
                      value: p.info.system.available_memory,
                      label: "Available",
                    },
                    {
                      id: 1,
                      value: p.info.system.used_memory,
                      label: "Used",
                    },
                  ],
                },
              ]}
              width={400}
              height={200}
            />
          </Box>
        </Grid>

        {/* Disk usage */}
        <Grid size={{ xs: 4 }}>
          <Box flexGrow={1}>
            <Typography style={{ textAlign: "center" }}>Disk usage</Typography>
            <PieChart
              series={[
                {
                  data: [
                    {
                      id: 1,
                      value: sumDiskUsage.free,
                      label: "Free",
                    },

                    {
                      id: 2,
                      value: sumDiskUsage.used,
                      label: "Used",
                    },
                  ],
                },
              ]}
              width={400}
              height={200}
            />
          </Box>
        </Grid>

        {/* CPU usage */}
        <Grid size={{ xs: 4 }}>
          <Box flexGrow={1}>
            <Typography style={{ textAlign: "center" }}>CPU usage</Typography>
            <PieChart
              series={[
                {
                  data: [
                    {
                      id: 1,
                      value: 100 - p.info.system.global_cpu_usage,
                      label: "Free",
                    },

                    {
                      id: 2,
                      value: p.info.system.global_cpu_usage,
                      label: "Used",
                    },
                  ],
                },
              ]}
              width={400}
              height={200}
            />
          </Box>
        </Grid>
      </Grid>

      <SysInfoDetailsTable
        label="General"
        icon={<Icon size={"1rem"} path={mdiInformation} />}
        entries={[
          {
            label: "Load",
            value: `${p.info.system.load_average.one} ${p.info.system.load_average.five} ${p.info.system.load_average.fifteen}`,
          },
          {
            label: "Uptime",
            value: humanizeDuration(p.info.system.uptime * 1000),
          },
          {
            label: "Bootime",
            value: new Date(p.info.system.boot_time * 1000).toString(),
          },
          {
            label: "Hypvervisor type",
            value: p.info.hypervisor.type,
          },
        ]}
      />

      <SysInfoDetailsTable
        label="CPU info"
        icon={<Icon size={"1rem"} path={mdiMemory} />}
        entries={[
          { label: "Brand", value: p.info.system.cpus[0].brand },
          {
            label: "Vendor ID",
            value: p.info.system.cpus[0].vendor_id,
          },
          {
            label: "CPU usage",
            value: p.info.system.cpus[0].cpu_usage,
          },
          {
            label: "Name",
            value: p.info.system.cpus[0].name,
          },
          {
            label: "CPU model",
            value: p.info.hypervisor.node.cpu_model,
          },
          {
            label: "CPU frequency (MHz)",
            value: p.info.hypervisor.node.cpu_frequency_mhz,
          },
          {
            label: "Number of socket",
            value: p.info.hypervisor.node.number_of_cpu_socket_per_node,
          },
          {
            label: "Number of cores per socket",
            value: p.info.hypervisor.node.number_of_core_per_sockets,
          },
          {
            label: "Number of threads per core",
            value: p.info.hypervisor.node.number_of_threads_per_core,
          },
        ]}
      />

      <SysInfoDetailsTable
        label="OS info"
        icon={<Icon size={"1rem"} path={mdiPackageVariantClosed} />}
        entries={[
          { label: "Name", value: p.info.system.name },
          { label: "Host name", value: p.info.system.host_name },
          { label: "Long OS version", value: p.info.system.long_os_version },
          { label: "Kernel version", value: p.info.system.kernel_version },
        ]}
      />

      <DiskDetailsTable disks={p.info.disks} />
      <NetworksDetailsTable networks={p.info.networks} />
    </VirtWebRouteContainer>
  );
}

function SysInfoDetailsTable(p: {
  label: string;
  icon: React.ReactElement;
  entries: { label: string; value: string | number }[];
}): React.ReactElement {
  return (
    <VirtWebPaper
      label={
        <>
          {p.icon} {p.label}
        </>
      }
    >
      <Table>
        <TableBody>
          {p.entries.map((e, c) => (
            <TableRow hover key={c}>
              <TableCell style={{ padding: 5, fontWeight: "bold" }}>
                {e.label}
              </TableCell>
              <TableCell style={{ padding: 5 }}>{e.value}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </VirtWebPaper>
  );
}

function DiskDetailsTable(p: { disks: DiskInfo[] }): React.ReactElement {
  return (
    <VirtWebPaper
      label={
        <>
          <Icon size={1} path={mdiHarddisk} /> Storage
        </>
      }
    >
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>Name</TableCell>
            <TableCell>Kind</TableCell>
            <TableCell>Mount point</TableCell>
            <TableCell>Total space</TableCell>
            <TableCell>Free space</TableCell>
            <TableCell></TableCell>
            <TableCell>Removable</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {p.disks.map((e, c) => (
            <TableRow hover key={c}>
              <TableCell>{e.name}</TableCell>
              <TableCell>{e.DiskKind}</TableCell>
              <TableCell>{e.mount_point}</TableCell>
              <TableCell>{filesize(e.total_space)}</TableCell>
              <TableCell>{filesize(e.available_space)}</TableCell>
              <TableCell>
                <LinearProgress
                  variant="determinate"
                  style={{ minWidth: "100px", width: "100%" }}
                  value={
                    100 * ((e.total_space - e.available_space) / e.total_space)
                  }
                />
              </TableCell>
              <TableCell>{e.is_removable ? "Yes" : "No"}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </VirtWebPaper>
  );
}

function NetworksDetailsTable(p: {
  networks: NetworkInfo[];
}): React.ReactElement {
  return (
    <VirtWebPaper
      label={
        <>
          <Icon size={1} path={mdiNetwork} /> Networks
        </>
      }
    >
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>Name</TableCell>
            <TableCell>Total received</TableCell>
            <TableCell>Total transmitted</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {p.networks.map((e, c) => (
            <TableRow hover key={c}>
              <TableCell>{e[0]}</TableCell>
              <TableCell>{filesize(e[1].total_received)}</TableCell>
              <TableCell>{filesize(e[1].total_transmitted)}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </VirtWebPaper>
  );
}
