import BackIcon from '@mui/icons-material/ArrowBack';
import NavigateBeforeIcon from '@mui/icons-material/NavigateBefore';
import NavigateNextIcon from '@mui/icons-material/NavigateNext';
import ReplayIcon from '@mui/icons-material/Replay';
import { AppBar, Backdrop, Box, Button, Grid, Stack, TextField, Toolbar, Typography } from '@mui/material';
import { FC, useRef, useState } from 'react';
import { v4 } from 'uuid';
import { MAX_LIST } from '../../constants';
import { useData } from '../../contexts/DataContext';
import { useRouter } from '../../routers/Router';

const getPages = (dirCount: number) => {
  const int = Math.floor(dirCount / MAX_LIST);
  const rem = dirCount & MAX_LIST;
  return rem === 0 && int > 0 ? int - 1 : int;
};

const ListPage: FC = () => {
  const { navigate, getProps } = useRouter();
  const { list, isLoading, refresh } = useData();
  const { path: _path } = getProps() as { path: string };

  const guid = useRef(v4());

  const [path, setPath] = useState(_path ?? '/');
  const [offset, setOffset] = useState(_path ? new Array(_path.split('/').length).fill(0) : [0]);
  const [pageJump, setPageJump] = useState('1');

  return (
    <Box>
      <AppBar position="sticky">
        <Toolbar>
          {path != '/' ? (
            <>
              <Button
                startIcon={<BackIcon htmlColor="white" />}
                onClick={() => {
                  setPath((prev) => {
                    let newPath = prev.split('/').slice(0, -2).join('/') + '/';
                    if (newPath === '/') newPath = '/';
                    setOffset((_prev) => {
                      _prev.pop();
                      return [..._prev];
                    });
                    refresh(newPath);
                    return newPath;
                  });
                }}
              >
                <Typography variant="h5" color="#fff">
                  Back
                </Typography>
              </Button>
              <Typography variant="h5" fontWeight="bold" textOverflow="ellipsis" component="div" sx={{ flexGrow: 1 }}>
                {path.split('/').slice(-2, -1)}
              </Typography>
            </>
          ) : (
            <Typography variant="h5" fontWeight="bold" component="div" sx={{ flexGrow: 1 }}>
              Files
            </Typography>
          )}
          {getPages(list.length) > 0 && (
            <>
              <TextField
                variant="filled"
                value={pageJump}
                sx={{ input: { color: '#fff' }, width: '100px' }}
                onChange={(e) => {
                  e.stopPropagation();
                  setPageJump(e.target.value);
                }}
                onFocus={() => Coherent.trigger('FOCUS_INPUT_FIELD', guid, '', '', '', false)}
                onBlur={() => Coherent.trigger('UNFOCUS_INPUT_FIELD', guid)}
              />
              <Button
                onClick={() => {
                  try {
                    let page = Number.parseInt(pageJump);
                    if (isNaN(page)) page = offset.slice(-1)[0];
                    page = Math.max(1, Math.min(getPages(list.length) + 1, page));
                    if ((page - 1) * MAX_LIST !== offset.slice(-1)[0]) {
                      setOffset((prev) => {
                        prev.pop();
                        return [...prev, (page - 1) * MAX_LIST];
                      });
                      setPageJump(`${page}`);
                    }
                  } catch (e) {
                    console.warn(e);
                  }
                }}
              >
                <Typography variant="h5" color="#fff">
                  Go to
                </Typography>
              </Button>
              <Button
                onClick={() => {
                  setOffset((prev) => {
                    const curOffset = offset.slice(-1)[0];
                    const newOffset = curOffset - MAX_LIST >= 0 ? curOffset - MAX_LIST : 0;
                    if (newOffset !== curOffset) {
                      prev.pop();
                      return [...prev, newOffset];
                    } else return prev;
                  });
                }}
              >
                <NavigateBeforeIcon htmlColor="white" fontSize="large" />
              </Button>
              <Typography variant="h5">
                {offset.slice(-1)[0] / MAX_LIST + 1}/{getPages(list.length) + 1}
              </Typography>
              <Button
                onClick={() => {
                  setOffset((prev) => {
                    const curOffset = offset.slice(-1)[0];
                    const newOffset = curOffset + MAX_LIST < list.length ? curOffset + MAX_LIST : curOffset;
                    if (newOffset !== curOffset) {
                      prev.pop();
                      return [...prev, newOffset];
                    } else return prev;
                  });
                }}
              >
                <NavigateNextIcon htmlColor="white" fontSize="large" />
              </Button>
            </>
          )}
          <Button
            onClick={() => {
              setOffset((prev) => {
                prev.pop();
                return [...prev, 0];
              });
              refresh(path);
            }}
          >
            <ReplayIcon htmlColor="white" fontSize="large" />
          </Button>
        </Toolbar>
      </AppBar>
      {isLoading ? (
        <Backdrop sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }} open>
          <Typography variant="h1">Loading...</Typography>
        </Backdrop>
      ) : (
        <Stack spacing={2}>
          {list.slice(offset.slice(-1)[0], offset.slice(-1)[0] + MAX_LIST).map((entry) => (
            <Grid
              key={entry.name}
              bgcolor="primary.main"
              onClick={() => {
                if (entry.type === 'directory') {
                  setPath(`${path}${entry.name}/`);
                  setOffset((prev) => [...prev, 0]);
                  refresh(`${path}${entry.name}/`);
                }
                if (entry.type === 'file') navigate('/file', { path, entry });
              }}
              container
              padding={1}
              height={73}
            >
              {entry.type === 'file' && (
                <Grid item xs={1} padding={0}>
                  <img src={`data:image/png;base64,${entry.thumb}`} width={40} height={57} />
                </Grid>
              )}
              <Grid item xs={11} padding={0}>
                <Box display="flex" alignItems="center" height="100%">
                  <Typography variant="h5" overflow="ellipsis">
                    {entry.name}
                  </Typography>
                </Box>
              </Grid>
              {entry.type === 'directory' && (
                <Grid item xs={1} padding={0} display="flex" alignItems="center">
                  <NavigateNextIcon htmlColor="white" fontSize="large" />
                </Grid>
              )}
            </Grid>
          ))}
        </Stack>
      )}
    </Box>
  );
};

export default ListPage;
