// material-ui
import { AlertFilled, AppstoreAddOutlined, CloseSquareOutlined, DeleteOutlined, PauseCircleOutlined, PlaySquareOutlined, PlusCircleOutlined, ReloadOutlined, RollbackOutlined, SearchOutlined, SettingOutlined, StopOutlined, UpCircleOutlined, UpSquareFilled, WarningFilled } from '@ant-design/icons';
import { Alert, Badge, Button, Card, Checkbox, Chip, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Divider, IconButton, Input, InputAdornment, TextField, Tooltip, Typography } from '@mui/material';
import Grid2 from '@mui/material/Unstable_Grid2/Grid2';
import { Stack } from '@mui/system';
import { useEffect, useState } from 'react';
import Paper from '@mui/material/Paper';
import { styled } from '@mui/material/styles';

import * as API from '../../api';
import IsLoggedIn from '../../isLoggedIn';
import RestartModal from '../config/users/restart';
import RouteManagement from '../config/routes/routeman';
import { ValidateRoute, getFaviconURL, sanitizeRoute, getContainersRoutes } from '../../utils/routes';
import HostChip from '../../components/hostChip';
import { Link } from 'react-router-dom';
import ExposeModal from './exposeModal';
import GetActions from './actionBar';
import ResponsiveButton from '../../components/responseiveButton';
import DockerComposeImport from './containers/docker-compose';
import { ContainerNetworkWarning } from '../../components/containers';
import { ServAppIcon } from '../../utils/servapp-icon';
import MiniPlotComponent from '../dashboard/components/mini-plot';
import { DownloadFile } from '../../api/downloadButton';

const Item = styled(Paper)(({ theme }) => ({
  backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
  ...theme.typography.body2,
  padding: theme.spacing(1),
  textAlign: 'center',
  color: theme.palette.text.secondary,
}));

const noOver = {
  overflowX: 'auto',
  width: "100%",
  maxWidth: "800px",
  height: "50px"
}

const ServApps = () => {
  const [servApps, setServApps] = useState([]);
  const [isUpdating, setIsUpdating] = useState({});
  const [search, setSearch] = useState("");
  const [config, setConfig] = useState(null);
  const [updatesAvailable, setUpdatesAvailable] = useState(null);
  const [openModal, setOpenModal] = useState(false);
  const [newRoute, setNewRoute] = useState(null);
  const [submitErrors, setSubmitErrors] = useState([]);
  const [openRestartModal, setOpenRestartModal] = useState(false);
  const [selfName, setSelfName] = useState("");

  const refreshServApps = () => {
    API.docker.list().then((res) => {
      setServApps(res.data);
    });
    API.config.get().then((res) => {
      setConfig(res.data);
      setUpdatesAvailable(res.updates);
      setSelfName(res.hostname);
    });
    setIsUpdating({});
  };

  const setIsUpdatingId = (id, value) => {
    setIsUpdating({
      ...isUpdating,
      [id]: value
    });
  }

  useEffect(() => {
    refreshServApps();
  }, []);
  
  function updateRoutes(newRoute) {
    return API.config.addRoute(newRoute).then((res) => {
      setOpenModal(false);
      setOpenRestartModal(true);
    });
  }

  const gridAnim = {
    transition: 'all 0.2s ease',
    opacity: 1,
    transform: 'translateY(0px)',
    '&.MuiGrid2-item--hidden': {
      opacity: 0,
      transform: 'translateY(-20px)',
    },
  };

  const selectable = {
    cursor: 'pointer',
    "&:hover": {
      textDecoration: 'underline',
    }
  }

  const getFirstRoute = (app) => {
    let routes = getContainersRoutes(config, app.Names[0].replace('/', ''));
    if(routes.length > 0) {
      return routes[0];
    }
  }

  const getFirstRouteFavIcon = (app) => {
    let routes = getContainersRoutes(config, app.Names[0].replace('/', ''));
    if(routes.length > 0) {
      let url = getFaviconURL(routes[0]);
      return url;
    } else {
      return getFaviconURL('');
    }
  }

  return <div>
    <RestartModal openModal={openRestartModal} setOpenModal={setOpenRestartModal} config={config} newRoute />
    <ExposeModal
      openModal={openModal} 
      setOpenModal={setOpenModal}
      container={servApps.find((app) => {
        return app.Names[0].replace('/', '') === (openModal && openModal.Names[0].replace('/', ''));
      })}
      config={config}
      updateRoutes={
        (_newRoute) => {
          updateRoutes(_newRoute);
        }
      }
    />

    <Stack spacing={{xs: 1, sm: 1, md: 2 }}>
      <Stack direction="row" spacing={2}>
        <Input placeholder="Search"
          value={search}
          startAdornment={
            <InputAdornment position="start">
              <SearchOutlined />
            </InputAdornment>
          }
          onChange={(e) => {
            setSearch(e.target.value);
          }}
        />
        <ResponsiveButton variant="contained" startIcon={<ReloadOutlined />} onClick={() => {
          refreshServApps();
        }}>Refresh</ResponsiveButton>
        <Link to="/cosmos-ui/servapps/new-service">
          <ResponsiveButton
            variant="contained" 
            startIcon={<AppstoreAddOutlined />}
            >Start ServApp</ResponsiveButton>
        </Link>
        <DockerComposeImport refresh={refreshServApps}/>
        <DownloadFile
          filename={'backup.cosmos-compose.json'}
          label={'Export Docker Backup'}
          contentGetter={API.config.getBackup}
        />
      </Stack>
      
      <Grid2 container spacing={{xs: 1, sm: 1, md: 2 }}>
        {updatesAvailable && updatesAvailable.length && <Grid2 style={gridAnim} xs={12} item>
          <Item>
            <Alert severity="info">Update are available for {Object.keys(updatesAvailable).join(', ')}</Alert>
          </Item>
        </Grid2>}
        {servApps && servApps.filter(app => search.length < 2 || app.Names[0].toLowerCase().includes(search.toLowerCase())).map((app) => {
          return <Grid2 style={gridAnim} xs={12} sm={6} md={6} lg={6} xl={4} key={app.Id} item>
            <Item>
            <Stack justifyContent='space-around' direction="column" spacing={2} padding={2} divider={<Divider orientation="horizontal" flexItem />}>
              <Stack direction="column" spacing={0} alignItems="flex-start">
                <Stack style={{position: 'relative', overflowX: 'hidden', width: '100%'}} direction="row" spacing={2} alignItems="center">
                  <Typography variant="body2" color="text.secondary">
                    {
                      ({
                        "created": <Chip label="Created" color="warning" />,
                        "restarting": <Chip label="Restarting" color="warning" />,
                        "running": <Chip label="Running" color="success" />,
                        "removing": <Chip label="Removing" color="error" />,
                        "paused": <Chip label="Paused" color="info" />,
                        "exited": <Chip label="Exited" color="error" />,
                        "dead": <Chip label="Dead" color="error" />,
                      })[app.State]
                    }
                  </Typography>
                  <Stack direction="row" spacing={2} alignItems="center">
                    <ServAppIcon container={app} route={getFirstRoute(app)} className="loading-image" width="40px"/>
                    <Stack direction="column" spacing={0} alignItems="flex-start" style={{height: '40px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'no-wrap'}}>
                      <Typography  variant="h5" color="text.secondary">
                      {app.Names[0].replace('/', '')}&nbsp; 
                      </Typography>
                      <Typography color="text.secondary" style={{fontSize: '80%', whiteSpace: 'nowrap', overflow: 'hidden', maxWidth: '100%', textOverflow: 'ellipsis'}}>
                        {app.Image}
                      </Typography>
                    </Stack>
                  </Stack>
                </Stack>
                <Stack direction="row" spacing={1} width='100%'>
                  <GetActions 
                    Id={app.Names[0].replace('/', '')}
                    image={app.Image}
                    state={app.State}
                    setIsUpdatingId={setIsUpdatingId}
                    refreshServApps={refreshServApps}
                    updateAvailable={updatesAvailable && updatesAvailable[app.Names[0]]}
                  />
                </Stack>
              </Stack>
              <Stack margin={1} direction="column" spacing={1} alignItems="flex-start">
                <Typography  variant="h6" color="text.secondary">
                  Ports
                </Typography> 
                <Stack style={noOver} margin={1} direction="row" spacing={1}>
                  {app.Ports.filter(p => p.IP != '::').map((port) => {
                    return <Tooltip title={port.PublicPort ? 'Warning, this port is publicly accessible' : ''}>
                      <Chip style={{ fontSize: '80%' }} label={(port.PublicPort ? (port.PublicPort + ":") : '') + port.PrivatePort} color={port.PublicPort ? 'warning' : 'default'} />
                    </Tooltip>
                  })}
                </Stack>
              </Stack>
              <Stack margin={1} direction="column" spacing={1} alignItems="flex-start">
                <Typography  variant="h6" color="text.secondary">
                  Networks
                </Typography> 
                <Stack style={noOver} margin={1} direction="row" spacing={1}>
                  {app.NetworkSettings.Networks && Object.keys(app.NetworkSettings.Networks).map((network) => {
                    return <Chip style={{ fontSize: '80%' }} label={network} color={network === 'bridge' ? 'warning' : 'default'} />
                  })}
                </Stack>
              </Stack>
              {isUpdating[app.Names[0].replace('/', '')] ? <div>
                  <CircularProgress color="inherit" />
                </div>
              :
                <Stack margin={1} direction="column" spacing={1} alignItems="flex-start">
                  <Typography  variant="h6" color="text.secondary">
                    Settings {app.State !== 'running' ? '(Start container to edit)' : ''}
                  </Typography> 
                  <Stack style={{ fontSize: '80%' }} direction={"row"} alignItems="center">
                    <Checkbox
                      checked={app.Labels['cosmos-force-network-secured'] === 'true'}
                      disabled={app.State !== 'running'}
                      onChange={(e) => {
                        const name = app.Names[0].replace('/', '');
                        setIsUpdatingId(name, true);
                        API.docker.secure(name, e.target.checked).then(() => {
                          setTimeout(() => {
                            setIsUpdatingId(name, false);
                            refreshServApps();
                          }, 3000);
                        }).catch(() => {
                          setIsUpdatingId(name, false);
                          refreshServApps();
                        })
                      }}
                    /> Isolate Container Network <ContainerNetworkWarning container={app} />
                  </Stack>
                  <Stack style={{ fontSize: '80%' }} direction={"row"} alignItems="center">
                    <Checkbox
                      checked={app.Labels['cosmos-auto-update'] === 'true' ||
                        (selfName && app.Names[0].replace('/', '') == selfName && config.AutoUpdate)}
                      disabled={app.State !== 'running'}
                      onChange={(e) => {
                        const name = app.Names[0].replace('/', '');
                        setIsUpdatingId(name, true);
                        API.docker.autoUpdate(name, e.target.checked).then(() => {
                          setTimeout(() => {
                            setIsUpdatingId(name, false);
                            refreshServApps();
                          }, 3000);
                        }).catch(() => {
                          setIsUpdatingId(name, false);
                          refreshServApps();
                        })
                      }}
                    /> Auto Update Container
                  </Stack>
                </Stack>
              }
              <Stack margin={1} direction="column" spacing={1} alignItems="flex-start">
                <Typography  variant="h6" color="text.secondary">
                  URLs
                </Typography>
                <Stack style={noOver} spacing={2} direction="row">
                  {getContainersRoutes(config, app.Names[0].replace('/', '')).map((route) => {
                    return <HostChip route={route} settings/>
                  })}
                  {/* {getContainersRoutes(config, app.Names[0].replace('/', '')).length == 0 && */}
                    <Chip 
                      label="New"
                      color="primary"
                      style={{paddingRight: '4px'}}
                      deleteIcon={<PlusCircleOutlined />}
                      onClick={() => {
                        setOpenModal(app);
                      }}
                      onDelete={() => {
                        setOpenModal(app);
                      }}
                    />
                    {/* } */}
                </Stack>
              </Stack>
              <div>
                <MiniPlotComponent agglo metrics={[
                  "cosmos.system.docker.cpu." + app.Names[0].replace('/', ''),
                  "cosmos.system.docker.ram." + app.Names[0].replace('/', ''),
                ]} labels={{
                  ["cosmos.system.docker.cpu." + app.Names[0].replace('/', '')]: "CPU", 
                  ["cosmos.system.docker.ram." + app.Names[0].replace('/', '')]: "RAM"
                }}/>
              </div>
              <div>
                <Link to={`/cosmos-ui/servapps/containers/${app.Names[0].replace('/', '')}`}>
                  <Button variant="outlined" color="primary" fullWidth>Details</Button>
                </Link>
              </div>
              {/* <Stack>
                <Button variant="contained" color="primary" onClick={() => {
                  setOpenModal(app);
                }}>Connect</Button>
              </Stack> */}
            </Stack>
          </Item></Grid2>
        })
        }
      </Grid2>
    </Stack>
  </div>
}

export default ServApps;
