import React, { PureComponent } from 'react';
import { withStyles } from '@mui/styles';
import PropTypes from 'prop-types';
import { Button, CircularProgress, Collapse, Grid, IconButton, List, ListItem, ListItemButton, ListItemText, Paper,
  Typography } from '@mui/material';
import { withTranslation } from 'react-i18next';
import { uploadLicenseData } from '../actions/license';
import { connect } from 'react-redux';
import TableViewContainer from '../components/TableViewContainer';
import { fetchDomainData } from '../actions/domains';
import { ExpandLess, ExpandMore } from '@mui/icons-material';
import { fetchPlainUsersData, fetchUserCount } from '../actions/users';

const styles = theme => ({
  paper: {
    margin: theme.spacing(3, 2, 3, 2),
    padding: theme.spacing(2, 2, 2, 2),
  },
  description: {
    display: 'inline-block',
    fontWeight: 500,
    width: 200,
  },
  data: {
    padding: '8px 0',
  },
  licenseContainer: {
    margin: theme.spacing(1, 0, 1, 0),
  },
  buyNow: {
    margin: theme.spacing(0, 0, 0, 1),
  },
  headline: {
    marginRight: 8,
  },
  gridItem: {
    display: 'flex',
    flex: 1,
  },
  progressContainer: {
    display: 'flex',
    justifyContent: 'center',
    margin: theme.spacing(1),
  },
});

class License extends PureComponent {

  state = {
    snackbar: '',
    domainsExpanded: false,
    expandedDomainIdxs: [],
    domainUsers: {},
    counts: {},
  }

  componentDidMount() {
    this.props.fetchDomains()
      .then(async () => {
        const { Domains, fetchCount } = this.props;
        const counts = {};
        Domains.forEach(async domain => counts[domain.domainname] = await fetchCount(domain.ID));
        this.setState({ counts });
      })
      .catch(snackbar => this.setState({ snackbar }));
  }

  handleUpload = () => {
    this.imageInputRef.click();
  }

  handleUploadConfirm = event => {
    this.props.upload(event.target.files[0])
      .then(() => this.setState({ snackbar: 'Success!' }))
      .catch(snackbar => this.setState({ snackbar }));
  }

  handleExpansion = (ID, idx) => () => {
    const { expandedDomainIdxs, domainUsers } = this.state;
    const copy = [...expandedDomainIdxs];
    if(copy.includes(idx)) {
      copy.splice(copy.findIndex(arrayIdx => arrayIdx === idx), 1);
    } else {
      if(!domainUsers[ID]) this.fetchUsers(ID);
      copy.push(idx);
    }
    this.setState({ expandedDomainIdxs: copy });
  }

  fetchUsers = async id => {
    const users = await this.props.fetchUsers(id)
      .catch(snackbar => this.setState({ snackbar }));
    this.setState({
      domainUsers: {
        ...this.state.domainUsers,
        [id]: users.data,
      },
    });
  }

  handleNavigation = domainID => () => {
    this.props.history.push(`/${domainID}/users`);
  }

  toggleDomainExpansion = () => this.setState({ domainsExpanded: !this.state.domainsExpanded });

  render() {
    const { classes, t, license, Domains } = this.props;
    const { snackbar, expandedDomainIdxs, domainUsers, domainsExpanded, counts } = this.state;

    return (
      <TableViewContainer
        headline={t("License")}
        subtitle={t('license_sub')}
        href="https://docs.grommunio.com/admin/administration.html#license"
        snackbar={snackbar}
        onSnackbarClose={() => this.setState({ snackbar: '' })}
      >
        <Paper className={classes.paper} elevation={1}>
          <Grid container alignItems="center">
            <Grid item className={classes.gridItem}>
              <Button
                variant="contained"
                color="primary"
                onClick={this.handleUpload}
                size="small"
              >
                {t('Upload')}
              </Button>
            </Grid>
            <Typography variant="body2">{t("Don't have a license?")}</Typography>
            <Button
              className={classes.buyNow}
              variant="contained"
              color="primary"
              href="https://grommunio.com/product/"
              target="_blank"
              size="small"
            >
              {t('Buy now')}
            </Button>
          </Grid>
          <Grid container direction="column" className={classes.licenseContainer}>
            <Typography className={classes.data}>
              <span className={classes.description}>{t('Product')}:</span>
              {license.product}
            </Typography>
            <Typography className={classes.data}>
              <span className={classes.description}>{t('Created')}:</span>
              {license.notBefore}
            </Typography>
            <Typography className={classes.data}>
              <span className={classes.description}>{t('Expires')}:</span>
              {license.notAfter}
            </Typography>
            <Typography className={classes.data}>
              <span className={classes.description}>{t('Users')}:</span>
              {license.currentUsers}
              <IconButton onClick={this.toggleDomainExpansion} size="small">
                {domainsExpanded ? <ExpandLess /> : <ExpandMore />}
              </IconButton>
            </Typography>
            <Collapse in={domainsExpanded} unmountOnExit>
              <List>
                {Domains.map(({ ID, domainname }, idx) => <React.Fragment key={idx}>
                  <ListItemButton onClick={this.handleExpansion(ID, idx)}>
                    <ListItemText
                      primary={`${domainname} (${counts[domainname] || 0})`}
                    />
                    {expandedDomainIdxs.includes(idx) ? <ExpandLess /> : <ExpandMore />}
                  </ListItemButton>
                  <Collapse in={expandedDomainIdxs.includes(idx)} unmountOnExit>
                    <List component="div" disablePadding>
                      {domainUsers[ID] ? domainUsers[ID].map((user, idx) => 
                        <ListItem key={idx} sx={{ pl: 4 }}>
                          <ListItemText primary={user.username}/>
                        </ListItem> 
                      ) : <div className={classes.progressContainer}>
                        <CircularProgress/>
                      </div>}
                      <ListItemButton onClick={this.handleNavigation(ID)} sx={{ pl: 4 }}>
                        <ListItemText primary={t('View all') + "..."}/>
                      </ListItemButton>
                    </List>
                  </Collapse>
                </React.Fragment>)}
              </List>
            </Collapse>
            <Typography className={classes.data}>
              <span className={classes.description}>{t('Max users')}:</span>
              {license.maxUsers}
            </Typography>
          </Grid>
          <input
            accept=".crt,.pem"
            style={{ display: 'none' }}
            id="license-upload-input"
            type="file"
            ref={r => (this.imageInputRef = r)}
            onChange={this.handleUploadConfirm}
          />
        </Paper>
      </TableViewContainer>
    );
  }
}

License.propTypes = {
  classes: PropTypes.object.isRequired,
  t: PropTypes.func.isRequired,
  history: PropTypes.object.isRequired,
  license: PropTypes.object.isRequired,
  upload: PropTypes.func.isRequired,
  fetchDomains: PropTypes.func.isRequired,
  fetchUsers: PropTypes.func.isRequired,
  fetchCount: PropTypes.func.isRequired,
  Domains: PropTypes.array.isRequired,
};

const mapStateToProps = state => {
  const { license, domains } = state;
  return {
    license: license.License,
    Domains: domains.Domains,
  };
};

const mapDispatchToProps = dispatch => {
  return {
    fetchDomains: async () => {
      await dispatch(fetchDomainData({ sort: 'domainname,asc', level: 0, limit: 10000 }))
        .catch(error => Promise.reject(error));
    },
    fetchCount: async domainID => await dispatch(fetchUserCount(domainID))
      .catch(error => Promise.reject(error)),
    fetchUsers: async (domainID) => 
      await dispatch(fetchPlainUsersData(domainID, { status: 0 }))
        .catch(error => Promise.reject(error)),
    upload: async license => await dispatch(uploadLicenseData(license))
      .catch(err => Promise.reject(err)),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(
  withTranslation()(withStyles(styles)(License)));