import {
  Box,
  Button,
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
  ListItem,
  ListItemText,
  Menu,
  TablePagination,
  TextField,
  Tooltip,
  Typography,
  useMediaQuery,
} from '@material-ui/core'
import FormControl from '@material-ui/core/FormControl'
import InputLabel from '@material-ui/core/InputLabel'
import MenuItem from '@material-ui/core/MenuItem'
import Paper from '@material-ui/core/Paper'
import Select from '@material-ui/core/Select'
import { createStyles, makeStyles, Theme, useTheme } from '@material-ui/core/styles'
import Table from '@material-ui/core/Table'
import TableBody from '@material-ui/core/TableBody'
import TableCell from '@material-ui/core/TableCell'
import TableContainer from '@material-ui/core/TableContainer'
import TableHead from '@material-ui/core/TableHead'
import TableRow from '@material-ui/core/TableRow'
import FileCopyIcon from '@material-ui/icons/FileCopy'
import LinkIcon from '@material-ui/icons/Link'
import MoreHorizIcon from '@material-ui/icons/MoreHoriz'
import RefreshIcon from '@material-ui/icons/Refresh'
import axios from 'axios'
import React, { useEffect } from 'react'
import { Link, useHistory } from 'react-router-dom'
import { getCompetitions, setFilterParams } from '../../../actions/competitions'
import { useAppDispatch, useAppSelector } from '../../../hooks'
import { Team } from '../../../interfaces/ApiModels'
import { CompetitionFilterParams } from '../../../interfaces/FilterParams'
import { FilterContainer, RemoveMenuItem, TopBar, YearFilterTextField } from '../styledComp'
import AddCompetition from './AddCompetition'

/**
 * Component description:
 * This component shows a list of all the competitions which a user can search through
 * We can also start, duplicate or delete a competition
 */

// Use defined styling
const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    table: {
      width: '100%',
    },
    margin: {
      margin: theme.spacing(1),
    },
    paper: {
      backgroundColor: theme.palette.background.paper,
      boxShadow: theme.shadows[5],
      padding: 4,
      outline: 'none',
    },
  })
)

interface Code {
  id: number
  code: string
  view_type_id: number
  competition_id: number
  team_id: number
}

const CompetitionManager: React.FC = (props: any) => {
  // for dialog alert
  const [openAlert, setOpen] = React.useState(false)
  const theme = useTheme()
  const fullScreen = useMediaQuery(theme.breakpoints.down('sm'))

  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
  const [activeId, setActiveId] = React.useState<number | undefined>(undefined)
  const [timerHandle, setTimerHandle] = React.useState<number | undefined>(undefined)
  const [dialogIsOpen, setDialogIsOpen] = React.useState(false)
  const [codes, setCodes] = React.useState<Code[]>([])
  const [teams, setTeams] = React.useState<Team[]>([])
  const [competitionName, setCompetitionName] = React.useState<string | undefined>(undefined)
  const loading = useAppSelector((state) => state.user.userInfo === null)
  const competitions = useAppSelector((state) => state.competitions.competitions)
  const filterParams = useAppSelector((state) => state.competitions.filterParams)
  const competitionTotal = useAppSelector((state) => state.competitions.total)
  const cities = useAppSelector((state) => state.cities.cities)
  const classes = useStyles()
  const noFilterText = 'Alla'
  const dispatch = useAppDispatch()
  const history = useHistory()

  const handleClick = (event: React.MouseEvent<HTMLButtonElement>, id: number) => {
    setActiveId(id)
    getCodes(id)
    getTeams(id)
    setAnchorEl(event.currentTarget)
  }

  const handleClose = () => {
    setAnchorEl(null)
    setActiveId(undefined)
  }

  const handleCloseVerify = () => {
    setOpen(false)
  }

  useEffect(() => {
    dispatch(getCompetitions())
  }, [])

  // Searchfuntion to search for a specific string
  const onSearchChange = (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
    if (timerHandle) {
      clearTimeout(timerHandle)
      setTimerHandle(undefined)
    }
    //Only updates filter and api 100ms after last input was made
    setTimerHandle(window.setTimeout(() => dispatch(getCompetitions()), 100))
    dispatch(setFilterParams({ ...filterParams, name: event.target.value }))
  }

  const handleVerifyDelete = () => {
    setOpen(true)
  }

  // Function to remove a competition from the systems database
  const handleDeleteCompetition = async () => {
    setOpen(false)
    if (activeId) {
      await axios
        .delete(`/api/competitions/${activeId}`)
        .then(() => {
          setAnchorEl(null)
          dispatch(getCompetitions()) // refresh the competition list
        })
        .catch(({ response }) => {
          console.warn(response.data)
        })
    }
  }

  /** Start the competition by redirecting with URL with Code */
  const handleStartCompetition = () => {
    const operatorCode = codes.find((code) => code.view_type_id === 4)?.code
    if (operatorCode) {
      history.push(`/${operatorCode}`)
    }
  }

  /** Fetch all the connection codes from the server */
  const getCodes = async (id: number) => {
    await axios
      .get(`/api/competitions/${id}/codes`)
      .then((response) => {
        setCodes(response.data.items)
      })
      .catch(console.log)
  }

  /** Fetch all the teams from the server that is connected to a specific competition*/
  const getTeams = async (id: number) => {
    await axios
      .get(`/api/competitions/${id}/teams`)
      .then((response) => {
        // console.log(response.data.items)
        setTeams(response.data.items)
      })
      .catch((err) => {
        console.log(err)
      })
  }

  /** Fetch the copetition name from the server */
  const getCompetitionName = async () => {
    await axios
      .get(`/api/competitions/${activeId}`)
      .then((response) => {
        // console.log(response.data.name)
        setCompetitionName(response.data.name)
      })
      .catch((err) => {
        console.log(err)
      })
  }

  const getTypeName = (code: Code) => {
    let typeName = ''
    switch (code.view_type_id) {
      case 1:
        const team = teams.find((team) => team.id === code.team_id)
        if (team) {
          typeName = team.name
        } else {
          typeName = 'Lagnamn hittades ej'
        }
        break
      case 2:
        typeName = 'Domare'
        break
      case 3:
        typeName = 'Publik'
        break
      case 4:
        typeName = 'Tävlingsoperatör'
        break
      default:
        typeName = 'Typ hittades ej'
        break
    }
    return typeName
  }

  /** Handles the opening of the code dialog box */
  const handleOpenDialog = async () => {
    await getCompetitionName()
    setDialogIsOpen(true)
  }
  /** Handles the closing of the code dialog box */
  const handleCloseDialog = () => {
    setDialogIsOpen(false)
    setAnchorEl(null)
  }

  /** Function that copies an existing competition */
  const handleDuplicateCompetition = async () => {
    if (activeId) {
      await axios
        .post(`/api/competitions/${activeId}/copy`)
        .then(() => {
          setAnchorEl(null)
          dispatch(getCompetitions())
        })
        .catch(({ response }) => {
          console.warn(response.data)
        })
    }
  }

  const handleFilterChange = (newParams: CompetitionFilterParams) => {
    dispatch(setFilterParams(newParams))
    dispatch(getCompetitions())
  }

  const refreshCode = async (code: Code) => {
    if (activeId) {
      await axios
        .put(`/api/competitions/${activeId}/codes/${code.id}`)
        .then(() => {
          getCodes(activeId)
          dispatch(getCompetitions())
        })
        .catch(({ response }) => {
          console.warn(response.data)
        })
    }
  }

  return (
    <div>
      <TopBar>
        <FilterContainer>
          <TextField className={classes.margin} value={filterParams.name || ''} onChange={onSearchChange} label="Sök" />
          <FormControl className={classes.margin}>
            <InputLabel shrink id="demo-customized-select-native">
              Region
            </InputLabel>
            <Select
              labelId="demo-customized-select-label"
              id="demo-customized-select"
              value={filterParams.cityId ? cities.find((city) => filterParams.cityId === city.id)?.name : noFilterText}
            >
              <MenuItem value={noFilterText} onClick={() => handleFilterChange({ ...filterParams, cityId: undefined })}>
                {noFilterText}
              </MenuItem>
              {cities &&
                cities.map((city) => (
                  <MenuItem
                    key={city.name}
                    value={city.name}
                    onClick={() => handleFilterChange({ ...filterParams, cityId: city.id })}
                  >
                    {city.name}
                  </MenuItem>
                ))}
            </Select>
          </FormControl>
          <YearFilterTextField
            label="År"
            name="model.year"
            type="number"
            value={filterParams.year || ''}
            onChange={(event) => handleFilterChange({ ...filterParams, year: +event.target.value })}
            margin="normal"
          />
        </FilterContainer>
        {!loading && <AddCompetition />}
      </TopBar>
      <TableContainer component={Paper}>
        <Table className={classes.table} aria-label="simple table">
          <TableHead>
            <TableRow>
              <TableCell>Namn</TableCell>
              <TableCell align="right">Region</TableCell>
              <TableCell align="right">År</TableCell>
              <TableCell align="right"></TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {competitions &&
              competitions.map((row) => (
                <TableRow key={row.name}>
                  <TableCell scope="row">
                    <Button color="primary" component={Link} to={`/editor/competition-id=${row.id}`}>
                      {row.name}
                    </Button>
                  </TableCell>
                  <TableCell align="right">{cities.find((city) => city.id === row.city_id)?.name || ''}</TableCell>
                  <TableCell align="right">{row.year}</TableCell>
                  <TableCell align="right">
                    <Button onClick={(event) => handleClick(event, row.id)} data-testid={row.name}>
                      <MoreHorizIcon />
                    </Button>
                  </TableCell>
                </TableRow>
              ))}
          </TableBody>
        </Table>
        {/** We can't find any competitions at all or with a specific filter */}
        {(!competitions || competitions.length === 0) && (
          <Typography>Inga tävlingar hittades med nuvarande filter</Typography>
        )}
      </TableContainer>
      <TablePagination
        component="div"
        rowsPerPageOptions={[]}
        rowsPerPage={filterParams.pageSize}
        count={competitionTotal}
        page={filterParams.page}
        onChangePage={(event, newPage) => handleFilterChange({ ...filterParams, page: newPage })}
      />
      <Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}>
        <MenuItem onClick={handleStartCompetition}>Starta</MenuItem>
        <MenuItem onClick={handleOpenDialog}>Visa koder</MenuItem>
        <MenuItem onClick={handleDuplicateCompetition}>Duplicera</MenuItem>
        <RemoveMenuItem onClick={handleVerifyDelete} data-testid="removeCompetitionButton">
          Ta bort
        </RemoveMenuItem>
      </Menu>
      <Dialog
        fullScreen={fullScreen}
        open={openAlert}
        onClose={handleCloseVerify}
        aria-labelledby="responsive-dialog-title"
      >
        <DialogTitle id="responsive-dialog-title">{'Ta bort tävlingen?'}</DialogTitle>
        <DialogContent>
          <DialogContentText>
            Är du säker på att du vill ta bort tävlingen och all dess information från systemet?
          </DialogContentText>
        </DialogContent>
        <DialogActions>
          <Button autoFocus onClick={handleCloseVerify} color="primary">
            Avbryt
          </Button>
          <Button data-testid="acceptRemoveCompetition" onClick={handleDeleteCompetition} color="primary" autoFocus>
            Ta bort
          </Button>
        </DialogActions>
      </Dialog>

      <Dialog
        open={dialogIsOpen}
        onClose={handleCloseDialog}
        aria-labelledby="max-width-dialog-title"
        maxWidth="xl"
        fullWidth={false}
        fullScreen={false}
      >
        <DialogTitle id="max-width-dialog-title" className={classes.paper}>
          Koder för {competitionName}
        </DialogTitle>
        <DialogContent>
          {/* <DialogContentText>Här visas tävlingskoderna till den valda tävlingen.</DialogContentText> */}
          {codes.map((code) => (
            <ListItem key={code.id} style={{ display: 'flex' }}>
              <ListItemText primary={`${getTypeName(code)}: `} />
              <Typography component="div">
                <ListItemText style={{ textAlign: 'right', marginLeft: '10px' }}>
                  <Box fontFamily="Monospace" fontWeight="fontWeightBold">
                    {code.code}
                  </Box>
                </ListItemText>
              </Typography>
              <Tooltip title="Generera ny kod" arrow>
                <Button
                  margin-right="0px"
                  onClick={() => {
                    refreshCode(code)
                  }}
                >
                  <RefreshIcon fontSize="small" />
                </Button>
              </Tooltip>
              <Tooltip title="Kopiera kod" arrow>
                <Button
                  margin-right="0px"
                  onClick={() => {
                    navigator.clipboard.writeText(code.code)
                  }}
                >
                  <FileCopyIcon fontSize="small" />
                </Button>
              </Tooltip>
              <Tooltip title="Kopiera länk" arrow>
                <Button
                  margin-right="0px"
                  onClick={() => {
                    navigator.clipboard.writeText(`${window.location.host}/${code.code}`)
                  }}
                >
                  <LinkIcon fontSize="small" />
                </Button>
              </Tooltip>
            </ListItem>
          ))}
        </DialogContent>
        <DialogActions>
          <Button onClick={handleCloseDialog} color="primary">
            Stäng
          </Button>
        </DialogActions>
      </Dialog>
    </div>
  )
}

export default CompetitionManager