import {
  Checkbox,
  FormControlLabel,
  Paper,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableRow,
  Tooltip,
  Typography,
} from "@mui/material";
import React from "react";
import { NWFilter } from "../../api/NWFilterApi";
import { NetworkInfo } from "../../api/NetworksApi";
import { ServerApi } from "../../api/ServerApi";
import { APIToken, TokenRight } from "../../api/TokensApi";
import { VMInfo } from "../../api/VMApi";

export function TokenRightsEditor(p: {
  token: APIToken;
  editable: boolean;
  onChange?: () => void;
  vms: VMInfo[];
  groups: string[];
  networks: NetworkInfo[];
  nwFilters: NWFilter[];
  tokens: APIToken[];
}): React.ReactElement {
  return (
    <>
      {/* Virtual machines */}
      <RightsSection label="Virtual machines">
        <RouteRight
          {...p}
          right={{ verb: "POST", path: "/api/vm/create" }}
          label="Create a new virtual machine"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/vm/list" }}
          label="Get list of virtual machines"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/vnc" }}
          label="Establish VNC connection"
        />
      </RightsSection>

      <RightsSection label="VM configuration management">
        <Table size="small">
          <TableHead>
            <TableRow>
              <TableCell>VM name</TableCell>
              <TableCell align="center">Get definition</TableCell>
              <TableCell align="center">Update</TableCell>
              <TableCell align="center">Delete</TableCell>
              <TableCell align="center">Get XML definition</TableCell>
              <TableCell align="center">Get autostart</TableCell>
              <TableCell align="center">Set autostart</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {/* All VM operations */}
            <TableRow hover>
              <TableCell>
                <i>All</i>
              </TableCell>
              <CellRight {...p} right={{ verb: "GET", path: "/api/vm/*" }} />
              <CellRight {...p} right={{ verb: "PUT", path: "/api/vm/*" }} />
              <CellRight {...p} right={{ verb: "DELETE", path: "/api/vm/*" }} />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/src" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/autostart" }}
              />
              <CellRight
                {...p}
                right={{ verb: "PUT", path: "/api/vm/*/autostart" }}
              />
            </TableRow>

            {/* Per VM operations */}
            {p.vms.map((v, n) => (
              <TableRow hover key={n}>
                <TableCell>{v.name}</TableCell>
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}` }}
                  parent={{ verb: "GET", path: "/api/vm/*" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "PUT", path: `/api/vm/${v.uuid}` }}
                  parent={{ verb: "PUT", path: "/api/vm/*" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "DELETE", path: `/api/vm/${v.uuid}` }}
                  parent={{ verb: "DELETE", path: "/api/vm/*" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/src` }}
                  parent={{ verb: "GET", path: "/api/vm/*/src" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/autostart` }}
                  parent={{ verb: "GET", path: "/api/vm/*/autostart" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "PUT", path: `/api/vm/${v.uuid}/autostart` }}
                  parent={{ verb: "PUT", path: "/api/vm/*/autostart" }}
                />
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </RightsSection>

      <RightsSection label="VM maintenance">
        <Table size="small">
          <TableHead>
            <TableRow>
              <TableCell>VM name</TableCell>
              <TableCell align="center">Get state</TableCell>
              <TableCell align="center">Start</TableCell>
              <TableCell align="center">Shutdown</TableCell>
              <TableCell align="center">Kill</TableCell>
              <TableCell align="center">Reset</TableCell>
              <TableCell align="center">Suspend</TableCell>
              <TableCell align="center">Resume</TableCell>
              <TableCell align="center">Screenshot</TableCell>
              <TableCell align="center">VNC token</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {/* All VM operations */}
            <TableRow hover>
              <TableCell>
                <i>All</i>
              </TableCell>
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/state" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/start" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/shutdown" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/kill" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/reset" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/suspend" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/resume" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/screenshot" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/vm/*/vnc" }}
              />
            </TableRow>

            {/* Per VM operations */}
            {p.vms.map((v, n) => (
              <TableRow hover key={n}>
                <TableCell>{v.name}</TableCell>
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/state` }}
                  parent={{ verb: "GET", path: "/api/vm/*/state" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/start` }}
                  parent={{ verb: "GET", path: "/api/vm/*/start" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/shutdown` }}
                  parent={{ verb: "GET", path: "/api/vm/*/shutdown" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/kill` }}
                  parent={{ verb: "GET", path: "/api/vm/*/kill" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/reset` }}
                  parent={{ verb: "GET", path: "/api/vm/*/reset" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/suspend` }}
                  parent={{ verb: "GET", path: "/api/vm/*/suspend" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/resume` }}
                  parent={{ verb: "GET", path: "/api/vm/*/resume" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/screenshot` }}
                  parent={{ verb: "GET", path: "/api/vm/*/screenshot" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/vm/${v.uuid}/vnc` }}
                  parent={{ verb: "GET", path: "/api/vm/*/vnc" }}
                />
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </RightsSection>

      <RightsSection label="VM groups">
        <RouteRight
          {...p}
          right={{ verb: "POST", path: "/api/group/list" }}
          label="Get the list of groups"
        />

        <Table size="small">
          <TableHead>
            <TableRow>
              <TableCell>Group name</TableCell>
              <TableCell align="center">Get VM info</TableCell>
              <TableCell align="center">Start VM</TableCell>
              <TableCell align="center">Shutdown VM</TableCell>
              <TableCell align="center">Suspend VM</TableCell>
              <TableCell align="center">Resume VM</TableCell>
              <TableCell align="center">Kill VM</TableCell>
              <TableCell align="center">Reset VM</TableCell>
              <TableCell align="center">Screenshot VM</TableCell>
              <TableCell align="center">Get VM State</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {/* All Group operations */}
            <TableRow hover>
              <TableCell>
                <i>All</i>
              </TableCell>
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/group/*/vm/info" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/group/*/vm/start" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/group/*/vm/shutdown" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/group/*/vm/suspend" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/group/*/vm/resume" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/group/*/vm/kill" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/group/*/vm/reset" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/group/*/vm/screenshot" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/group/*/vm/state" }}
              />
            </TableRow>

            {/* Per VM operations */}
            {p.groups.map((v, n) => (
              <TableRow hover key={n}>
                <TableCell>{v}</TableCell>
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/group/${v}/vm/info` }}
                  parent={{ verb: "GET", path: "/api/group/*/vm/info" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/group/${v}/vm/start` }}
                  parent={{ verb: "GET", path: "/api/group/*/vm/start" }}
                />
                <CellRight
                  {...p}
                  right={{
                    verb: "GET",
                    path: `/api/group/${v}/vm/shutdown`,
                  }}
                  parent={{ verb: "GET", path: "/api/group/*/vm/shutdown" }}
                />
                <CellRight
                  {...p}
                  right={{
                    verb: "GET",
                    path: `/api/group/${v}/vm/suspend`,
                  }}
                  parent={{ verb: "GET", path: "/api/group/*/vm/suspend" }}
                />
                <CellRight
                  {...p}
                  right={{
                    verb: "GET",
                    path: `/api/group/${v}/vm/resume`,
                  }}
                  parent={{ verb: "GET", path: "/api/group/*/vm/resume" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/group/${v}/vm/kill` }}
                  parent={{ verb: "GET", path: "/api/group/*/vm/kill" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/group/${v}/vm/reset` }}
                  parent={{ verb: "GET", path: "/api/group/*/vm/reset" }}
                />
                <CellRight
                  {...p}
                  right={{
                    verb: "GET",
                    path: `/api/group/${v}/vm/screenshot`,
                  }}
                  parent={{ verb: "GET", path: "/api/group/*/vm/screenshot" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/group/${v}/vm/state` }}
                  parent={{ verb: "GET", path: "/api/group/*/vm/state" }}
                />
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </RightsSection>

      {/* Networks */}
      <RightsSection label="Networks">
        <RouteRight
          {...p}
          right={{ verb: "POST", path: "/api/network/create" }}
          label="Create a new network"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/network/list" }}
          label="Get list of networks"
        />
      </RightsSection>

      {/* Networks management */}
      <RightsSection label="Networks management">
        <Table size="small">
          <TableHead>
            <TableRow>
              <TableCell>Network name</TableCell>
              <TableCell align="center">Get definition</TableCell>
              <TableCell align="center">Update</TableCell>
              <TableCell align="center">Delete</TableCell>
              <TableCell align="center">Get XML definition</TableCell>
              <TableCell align="center">Get autostart</TableCell>
              <TableCell align="center">Set autostart</TableCell>
              <TableCell align="center">Get status</TableCell>
              <TableCell align="center">Start</TableCell>
              <TableCell align="center">Stop</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {/* All networks operations */}
            <TableRow hover>
              <TableCell>
                <i>All</i>
              </TableCell>
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/network/*" }}
              />
              <CellRight
                {...p}
                right={{ verb: "PUT", path: "/api/network/*" }}
              />
              <CellRight
                {...p}
                right={{ verb: "DELETE", path: "/api/network/*" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/network/*/src" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/network/*/autostart" }}
              />
              <CellRight
                {...p}
                right={{ verb: "PUT", path: "/api/network/*/autostart" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/network/*/status" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/network/*/start" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/network/*/stop" }}
              />
            </TableRow>

            {/* Per network operations */}
            {p.networks.map((v, n) => (
              <TableRow hover key={n}>
                <TableCell>{v.name}</TableCell>
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/network/${v.uuid}` }}
                  parent={{ verb: "GET", path: "/api/network/*" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "PUT", path: `/api/network/${v.uuid}` }}
                  parent={{ verb: "PUT", path: "/api/network/*" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "DELETE", path: `/api/network/${v.uuid}` }}
                  parent={{ verb: "DELETE", path: "/api/network/*" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/network/${v.uuid}/src` }}
                  parent={{ verb: "GET", path: "/api/network/*/src" }}
                />
                <CellRight
                  {...p}
                  right={{
                    verb: "GET",
                    path: `/api/network/${v.uuid}/autostart`,
                  }}
                  parent={{ verb: "GET", path: "/api/network/*/autostart" }}
                />
                <CellRight
                  {...p}
                  right={{
                    verb: "PUT",
                    path: `/api/network/${v.uuid}/autostart`,
                  }}
                  parent={{ verb: "PUT", path: "/api/network/*/autostart" }}
                />
                <CellRight
                  {...p}
                  right={{
                    verb: "GET",
                    path: `/api/network/${v.uuid}/status`,
                  }}
                  parent={{ verb: "GET", path: "/api/network/*/status" }}
                />
                <CellRight
                  {...p}
                  right={{
                    verb: "GET",
                    path: `/api/network/${v.uuid}/start`,
                  }}
                  parent={{ verb: "GET", path: "/api/network/*/start" }}
                />
                <CellRight
                  {...p}
                  right={{
                    verb: "GET",
                    path: `/api/network/${v.uuid}/stop`,
                  }}
                  parent={{ verb: "GET", path: "/api/network/*/stop" }}
                />
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </RightsSection>

      {/* Network filters */}
      <RightsSection label="Network filters">
        <RouteRight
          {...p}
          right={{ verb: "POST", path: "/api/nwfilter/create" }}
          label="Create a new network filter"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/nwfilter/list" }}
          label="Get list of network filters"
        />
      </RightsSection>

      {/* Networks filters management */}
      <RightsSection label="Networks filters management">
        <Table size="small">
          <TableHead>
            <TableRow>
              <TableCell>Network filter name</TableCell>
              <TableCell align="center">Get definition</TableCell>
              <TableCell align="center">Update</TableCell>
              <TableCell align="center">Delete</TableCell>
              <TableCell align="center">Get XML definition</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {/* All networks filters operations */}
            <TableRow hover>
              <TableCell>
                <i>All</i>
              </TableCell>
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/nwfilter/*" }}
              />
              <CellRight
                {...p}
                right={{ verb: "PUT", path: "/api/nwfilter/*" }}
              />
              <CellRight
                {...p}
                right={{ verb: "DELETE", path: "/api/nwfilter/*" }}
              />
              <CellRight
                {...p}
                right={{ verb: "GET", path: "/api/nwfilter/*/src" }}
              />
            </TableRow>

            {/* Per network filter operations */}
            {p.nwFilters.map((v, n) => (
              <TableRow hover key={n}>
                <TableCell>{v.name}</TableCell>
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/nwfilter/${v.uuid}` }}
                  parent={{ verb: "GET", path: "/api/nwfilter/*" }}
                />
                {ServerApi.Config.builtin_nwfilter_rules.includes(v.name!) ? (
                  <TableCell></TableCell>
                ) : (
                  <CellRight
                    {...p}
                    right={{ verb: "PUT", path: `/api/nwfilter/${v.uuid}` }}
                    parent={{ verb: "PUT", path: "/api/nwfilter/*" }}
                  />
                )}
                {ServerApi.Config.builtin_nwfilter_rules.includes(v.name!) ? (
                  <TableCell></TableCell>
                ) : (
                  <CellRight
                    {...p}
                    right={{ verb: "DELETE", path: `/api/nwfilter/${v.uuid}` }}
                    parent={{ verb: "DELETE", path: "/api/nwfilter/*" }}
                  />
                )}
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/nwfilter/${v.uuid}/src` }}
                  parent={{ verb: "GET", path: "/api/nwfilter/*/src" }}
                />
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </RightsSection>

      {/* API tokens */}
      <RightsSection label="API tokens">
        <RouteRight
          {...p}
          right={{ verb: "POST", path: "/api/token/create" }}
          label="Create a new API token"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/token/list" }}
          label="Get list of API tokens"
        />
      </RightsSection>

      {/* API tokens management */}
      <RightsSection label="API tokens management">
        <Table size="small">
          <TableHead>
            <TableRow>
              <TableCell>API token name</TableCell>
              <TableCell align="center">Get</TableCell>
              <TableCell align="center">Update</TableCell>
              <TableCell align="center">Delete</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {/* All API tokens operations */}
            <TableRow hover>
              <TableCell>
                <i>All</i>
              </TableCell>
              <CellRight {...p} right={{ verb: "GET", path: "/api/token/*" }} />
              <CellRight {...p} right={{ verb: "PUT", path: "/api/token/*" }} />
              <CellRight
                {...p}
                right={{ verb: "DELETE", path: "/api/token/*" }}
              />
            </TableRow>

            {/* Per API token operations */}
            {p.tokens.map((v, n) => (
              <TableRow hover key={n}>
                <TableCell>{v.name}</TableCell>
                <CellRight
                  {...p}
                  right={{ verb: "GET", path: `/api/token/${v.id}` }}
                  parent={{ verb: "GET", path: "/api/token/*" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "PUT", path: `/api/token/${v.id}` }}
                  parent={{ verb: "PUT", path: "/api/token/*" }}
                />
                <CellRight
                  {...p}
                  right={{ verb: "DELETE", path: `/api/token/${v.id}` }}
                  parent={{ verb: "DELETE", path: "/api/token/*" }}
                />
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </RightsSection>

      {/* ISO files */}
      <RightsSection label="ISO files">
        <RouteRight
          {...p}
          right={{ verb: "POST", path: "/api/iso/upload" }}
          label="Upload a new ISO file"
        />
        <RouteRight
          {...p}
          right={{ verb: "POST", path: "/api/iso/upload_from_url" }}
          label="Upload a new ISO file from a given URL"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/iso/list" }}
          label="Get the list of ISO files"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/iso/*" }}
          label="Download ISO files"
        />
        <RouteRight
          {...p}
          right={{ verb: "DELETE", path: "/api/iso/*" }}
          label="Delete ISO files"
        />
      </RightsSection>

      {/* Server general information */}
      <RightsSection label="Server">
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/server/static_config" }}
          label="Get static server configuration"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/server/info" }}
          label="Get server information"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/server/network_hook_status" }}
          label="Get network hook status"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/server/number_vcpus" }}
          label="Get number of vCPU"
        />
        <RouteRight
          {...p}
          right={{ verb: "GET", path: "/api/server/networks" }}
          label="Get list of network cards"
        />
      </RightsSection>
    </>
  );
}

function RightsSection(
  p: React.PropsWithChildren<{ label: string }>
): React.ReactElement {
  return (
    <Paper style={{ padding: "20px", margin: "10px" }}>
      <Typography variant="h5">{p.label}</Typography>
      {p.children}
    </Paper>
  );
}

interface RightOpts {
  right: TokenRight;
  label?: string;
  editable: boolean;
  token: APIToken;
  onChange?: () => void;
  parent?: TokenRight;
}

function CellRight(p: RightOpts): React.ReactElement {
  return (
    <TableCell align="center">
      <RouteRight {...p} />
    </TableCell>
  );
}

function RouteRight(p: RightOpts): React.ReactElement {
  const rightIndex = p.token.rights.findIndex(
    (r) => r.verb === p.right.verb && r.path === p.right.path
  );
  const activated = rightIndex !== -1;

  const parentActivated =
    !!p.parent &&
    p.token.rights.findIndex(
      (r) => r.verb === p.parent?.verb && r.path === p.parent?.path
    ) !== -1;

  const toggle = (a: boolean) => {
    if (a) {
      p.token.rights.push(p.right);
    } else {
      p.token.rights.splice(rightIndex, 1);
    }
    p.onChange?.();
  };

  return (
    <div>
      <Tooltip
        title={`${p.right.verb} ${p.right.path}`}
        arrow
        placement="left"
        slotProps={{
          popper: {
            modifiers: [
              {
                name: "offset",
                options: {
                  offset: [0, -14],
                },
              },
            ],
          },
        }}
      >
        {p.label ? (
          <FormControlLabel
            control={
              <Checkbox
                checked={activated || parentActivated}
                disabled={!p.editable || parentActivated}
                onChange={(_e, a) => toggle(a)}
              />
            }
            label={p.label}
          />
        ) : (
          <span>
            <Checkbox
              checked={activated || parentActivated}
              disabled={!p.editable || parentActivated}
              onChange={(_e, a) => toggle(a)}
            />
          </span>
        )}
      </Tooltip>
    </div>
  );
}
