import { Grid } from "@mui/material";
import React from "react";
import { validate as validateUUID } from "uuid";
import { IsoFile, IsoFilesApi } from "../../api/IsoFilesApi";
import { ServerApi } from "../../api/ServerApi";
import { VMApi, VMInfo } from "../../api/VMApi";
import { AsyncWidget } from "../AsyncWidget";
import { CheckboxInput } from "../forms/CheckboxInput";
import { EditSection } from "../forms/EditSection";
import { SelectInput } from "../forms/SelectInput";
import { TextInput } from "../forms/TextInput";
import { VMDisksList } from "../forms/VMDisksList";
import { VMSelectIsoInput } from "../forms/VMSelectIsoInput";
import { VMScreenshot } from "./VMScreenshot";
import { ResAutostartInput } from "../forms/ResAutostartInput";
import { VMNetworksList } from "../forms/VMNetworksList";
import { NetworkApi, NetworkInfo } from "../../api/NetworksApi";

interface DetailsProps {
  vm: VMInfo;
  editable: boolean;
  onChange?: () => void;
  screenshot?: boolean;
}

export function VMDetails(p: DetailsProps): React.ReactElement {
  const [isoList, setIsoList] = React.useState<IsoFile[] | any>();
  const [vcpuCombinations, setVCPUCombinations] = React.useState<
    number[] | any
  >();
  const [networksList, setNetworksList] = React.useState<NetworkInfo[] | any>();

  const load = async () => {
    setIsoList(await IsoFilesApi.GetList());
    setVCPUCombinations(await ServerApi.NumberVCPUs());
    setNetworksList(await NetworkApi.GetList());
  };

  return (
    <AsyncWidget
      loadKey={"1"}
      load={load}
      errMsg="Failed to load the list of ISO files"
      build={() => (
        <VMDetailsInner
          isoList={isoList}
          vcpuCombinations={vcpuCombinations}
          networksList={networksList}
          {...p}
        />
      )}
    />
  );
}

function VMDetailsInner(
  p: DetailsProps & {
    isoList: IsoFile[];
    vcpuCombinations: number[];
    networksList: NetworkInfo[];
  }
): React.ReactElement {
  return (
    <Grid container spacing={2}>
      {
        /* Screenshot section */ p.screenshot && (
          <EditSection title="Screenshot">
            <VMScreenshot vm={p.vm} />
          </EditSection>
        )
      }

      {/* Metadata section */}
      <EditSection title="Metadata">
        <TextInput
          label="Name"
          editable={p.editable}
          value={p.vm.name}
          onValueChange={(v) => {
            p.vm.name = v ?? "";
            p.onChange?.();
          }}
          checkValue={(v) => /^[a-zA-Z0-9]+$/.test(v)}
          size={ServerApi.Config.constraints.vm_name_size}
        />

        <TextInput label="UUID" editable={false} value={p.vm.uuid} />

        <TextInput
          label="VM genid"
          editable={p.editable}
          value={p.vm.genid}
          onValueChange={(v) => {
            p.vm.genid = v;
            p.onChange?.();
          }}
          checkValue={(v) => validateUUID(v)}
        />

        <TextInput
          label="Title"
          editable={p.editable}
          value={p.vm.title}
          onValueChange={(v) => {
            p.vm.title = v;
            p.onChange?.();
          }}
          size={ServerApi.Config.constraints.vm_title_size}
        />

        <TextInput
          label="Description"
          editable={p.editable}
          value={p.vm.description}
          onValueChange={(v) => {
            p.vm.description = v;
            p.onChange?.();
          }}
          multiline={true}
        />
      </EditSection>

      {/* General section */}
      <EditSection title="General">
        <SelectInput
          editable={p.editable}
          label="CPU Architecture"
          onValueChange={(v) => {
            p.vm.architecture = v! as any;
            p.onChange?.();
          }}
          value={p.vm.architecture}
          options={[
            { label: "i686", value: "i686" },
            { label: "x86_64", value: "x86_64" },
          ]}
        />

        <SelectInput
          editable={p.editable}
          label="Boot type"
          onValueChange={(v) => {
            p.vm.boot_type = v! as any;
            p.onChange?.();
          }}
          value={p.vm.boot_type}
          options={[
            { label: "UEFI with Secure Boot", value: "UEFISecureBoot" },
            { label: "UEFI", value: "UEFI" },
          ]}
        />

        <TextInput
          label="Memory (MB)"
          editable={p.editable}
          type="number"
          value={p.vm.memory.toString()}
          onValueChange={(v) => {
            p.vm.memory = Number(v ?? "0");
            p.onChange?.();
          }}
          checkValue={(v) =>
            Number(v) > ServerApi.Config.constraints.memory_size.min &&
            Number(v) < ServerApi.Config.constraints.memory_size.max
          }
        />

        <SelectInput
          editable={p.editable}
          label="Number of vCPU"
          options={p.vcpuCombinations.map((v) => {
            return { label: v.toString(), value: v.toString() };
          })}
          value={p.vm.number_vcpu.toString()}
          onValueChange={(v) => {
            p.vm.number_vcpu = Number(v ?? "0");
            p.onChange?.();
          }}
        />

        <CheckboxInput
          editable={p.editable}
          label="Enable VNC access"
          checked={p.vm.vnc_access}
          onValueChange={(v) => {
            p.vm.vnc_access = v;
            p.onChange?.();
          }}
        />

        {p.vm.uuid && (
          <ResAutostartInput
            editable={p.editable}
            ressourceName="VM"
            checkAutotostart={() => VMApi.IsAutostart(p.vm)}
            setAutotostart={(e) => VMApi.SetAutostart(p.vm, e)}
          />
        )}
      </EditSection>

      {/* Storage section */}
      <EditSection title="Storage">
        <VMSelectIsoInput
          editable={p.editable}
          isoList={p.isoList}
          attachedISOs={p.vm.iso_files}
          onChange={(v) => {
            p.vm.iso_files = v;
            p.onChange?.();
          }}
        />
        <VMDisksList {...p} />
      </EditSection>

      {/* Networks section */}
      <EditSection title="Networks">
        <VMNetworksList {...p} />
      </EditSection>
    </Grid>
  );
}
