import { AxiosInstance } from "axios"
import { ActionGroup, ActionInfo, DataTable, UserInfoContext, actionIdentifierContext, api, apiAuthenticatedContext } from "./common"
import { Context, Dispatch, createContext, useContext, useEffect, useState } from "react"
import { TableRow, TableCell, Chip } from "@mui/material"
import { PortMapping, ServerInfo } from "./interfaces"
import { CREATE_SERVER_ACTION, Permission, SERVER_ACTIONS } from "./actions"
import ContentCopyIcon from '@mui/icons-material/ContentCopy'



export async function loadServers(api: AxiosInstance): Promise<{ status: number, data: ServerInfo[] }> {
  let response = await api.get('/servers')
  return {
    status: response.status,
    data: response.data
  }
}

const serverActionsContext: Context<ActionInfo[]> = createContext([] as ActionInfo[])

function generateChipHandler(domain: string, port: PortMapping) {
  return () => {
    navigator.clipboard.writeText(`${domain}:${port.HostPort}`)
  }

}

function ServerItem(props: { server_info: ServerInfo }) {
  const actions = useContext(serverActionsContext)
  const [serverPermissions, setServerPermissions] = useState(null as null | number)
  const user = useContext(UserInfoContext)
  let permissions = 0
  console.log(user)
  if (props.server_info.OwnerId === user?.Username) {
    permissions |= Permission.Admin
  } else {
    if (serverPermissions === null) {
      api.get(`/servers/${props.server_info.Id}/permissions`).then((event) => { setServerPermissions(event.data) })
    } else {
      permissions |= serverPermissions
    }
    if (user) {
      permissions |= user.Permissions
    }
  }


  const name = `${props.server_info.OwnerId}'s ${props.server_info.Image.Name} ${props.server_info.Image.Version} Server`

  if (props.server_info.Ports === null) {
    props.server_info.Ports = []
  }

  return (
    <UserInfoContext.Provider value={user ? { Username: user.Username, Email: user.Email, Permissions: permissions } : null}>
      <actionIdentifierContext.Provider value={props.server_info.Id}>
        <TableRow>
          <TableCell>{props.server_info.Nickname}</TableCell>
          <TableCell>{props.server_info.OwnerId}</TableCell>
          <TableCell>{props.server_info.Image.Name}</TableCell>
          <TableCell>{props.server_info.Image.Version}</TableCell>
          <TableCell>{props.server_info.Domain}</TableCell>
          <TableCell>{props.server_info.Ports.map((port, index, array) => { return <Chip onClick={generateChipHandler(props.server_info.Domain, port)} label={`${port.HostPort}:${port.ContainerPort}/${port.Protocol}`} icon={<ContentCopyIcon />} /> })}</TableCell>
          <TableCell>
            <ActionGroup actions={actions.filter((value) => {
              switch (value.ServerState) {
                case undefined:
                  return true
                case "off":
                  return !props.server_info.On
                case "on":
                  return props.server_info.On
              }
            })} identifierSubstring="server_id" />
          </TableCell>
        </TableRow>
      </actionIdentifierContext.Provider>
    </UserInfoContext.Provider>
  )
}


export default function ServersBoard() {
  const [servers, setServers]: [ServerInfo[], Dispatch<ServerInfo[]>] = useState([] as ServerInfo[]);
  servers.sort()
  const [apiAuthenticated, setApiAuthenticated] = useContext(apiAuthenticatedContext)

  function handleServers() {
    if (!apiAuthenticated) {
      return
    }

    let servers_promised = loadServers(api)
    servers_promised.then((response) => {
      setServers(response.data)
    })
      .catch(
        (error) => {
          console.log('Failed to get servers: ' + error);
          if (error.response) {
            if (error.response.status === 401) {
              setApiAuthenticated(false)
            }
            else if (error.response.status === 403) {
              setApiAuthenticated(false)
            }
          }
        }
      )
  }


  useEffect(() => {
    handleServers()
    const interval = setInterval(() => {
      handleServers()
    }, 5000
    );
    return () => { clearInterval(interval) }
  }, [apiAuthenticated])



  return (
    <DataTable headers={['Nickname', 'Owner', 'Server', 'Version', 'Domain', 'Ports', 'Actions']} actionInfo={CREATE_SERVER_ACTION}>
      <serverActionsContext.Provider value={SERVER_ACTIONS}>
        {
          servers.sort((s1: ServerInfo, s2: ServerInfo) => { return s1.Id < s2.Id ? 0 : 1 }).map(
            (value: ServerInfo, index: number, array) => {
              return <ServerItem server_info={value} />
            }
          )
        }
      </serverActionsContext.Provider>
    </DataTable>
  );
}

