import * as React from 'react';
import { Box, Grid, ExpansionPanel, ExpansionPanelSummary, Typography, ExpansionPanelDetails, TextField, Button, Dialog, DialogTitle, DialogContent, DialogActions, Link, Container } from '@material-ui/core';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { chosenAlphabet, inputLoad, passwordLoad, writerToOutput, regexp, myAlert } from '../../basicLayout';

export interface IVigenereCipherProps {
    idInput: string,
    idOutput: string,
    idSwitch: string
}

export interface IVigenereCipherState {
    vigenereOutput: string
}

export default class VigenereCipher extends React.Component<IVigenereCipherProps, IVigenereCipherState> {
  constructor(props: IVigenereCipherProps) {
    super(props);

    this.state = {
      vigenereOutput: ""
    }

    this.vigenereDialog = this.vigenereDialog.bind(this);
  }

  public VigenereCipher(input: string[], alphabet: string[], password: string[], decrypt: boolean): string {
    var message: string = '';
    var passwordPointer: number = 0;

    input.forEach( e => {
      if (e.match(regexp)) {
          var upperCase = false;
          if(e === e.toUpperCase()) {
            upperCase = true;
            e = e.toLowerCase();
          }

          if(passwordPointer === password.length)
            passwordPointer = 0;

          //  ALPHABET SHIFT & DETERMINATION
          var firstAlphabetPart: string[] = alphabet.slice(0, alphabet.indexOf(password[passwordPointer]));
          var secondAlphabetPart: string[] = alphabet.slice(alphabet.indexOf(password[passwordPointer]), alphabet.length);
          var tmpAlphabet: string[] = (secondAlphabetPart).concat(firstAlphabetPart);
          
          if(decrypt)
            e = alphabet[tmpAlphabet.indexOf(e)];
          else
            e = tmpAlphabet[alphabet.indexOf(e)];

          if (upperCase)
            e = e.toUpperCase();
          passwordPointer++;
      }
      
      message += e;
    });

    return message;
  }

  private vigenereDialog () {
    const [open, setOpen] = React.useState(false);
    const handleClickOpen = () => {
      setOpen(true);
    };
    const handleClose = () => {
      setOpen(false);
    };
    
    return (
      <div>
        <Button variant="outlined" color="primary" onClick={handleClickOpen}>Tabula recta</Button>
        
        <Dialog
          open={open}
          onClose={handleClose}
        >
          <DialogTitle>Vigenère Table (<i>tabula recta</i>)</DialogTitle>
          <DialogContent>
            <Grid container className='columGrid'>
              <Grid container className='columGrid'>
                <img
                  src="http://www.stud.feec.vutbr.cz/~xrysav29/cipher_pics/tabula_recta.svg.png"
                  alt="Vigenère square shading"
                  width="100%"/>
              </Grid>
              <Typography variant='caption' style={{ color: '#808080' }} align='center'>
                <b>Img. 1.:</b> <i>Tabula recta by Brandon T. Fields (cdated, Public domain, <u>source</u>:{' '}
                <Link color='primary' href="https://commons.wikimedia.org/wiki/File:Vigen%C3%A8re_square_shading.svg" target="_blank" rel="noopener noreferrer">
                  commons.wikimedia.org
                </Link>).</i>
              </Typography>
            </Grid>
          </DialogContent>
          <DialogActions style={{alignSelf: 'center'}}>
            <Box my={3}>
              <Button onClick={handleClose} color="primary" autoFocus>CLOSE</Button>
            </Box>
          </DialogActions>
        </Dialog>
      </div>
    );
  }

  public render() {
    var EDswitch: boolean = false;
    if(document.getElementById(this.props.idSwitch) && (document.getElementById(this.props.idSwitch) as HTMLInputElement).checked)
      EDswitch = true;

    return (
      <div>
          <Grid container className='rowGrid'>
            <Box my={2}>
              <TextField
                required
                id="passwordVigener"
                label="Password"
                defaultValue='SECRET'
                helperText="Please typedown the chosen password."
                InputLabelProps={{
                  shrink: true,
                }}
                className='smallTextField'
              />
            </Box>

            <Container>
              <Button
                size="large"
                variant="contained"
                color="primary"
                autoFocus
                onClick={ () => {
                  this.forceUpdate();
                  if ((document.getElementById("passwordVigener") as HTMLInputElement).value === '') {
                    var tmp = myAlert("Password isn't defined! Please define the password:", 'enter', ['secret']);
                    if( tmp != null )
                      (document.getElementById("passwordVigener") as HTMLInputElement).value = String(tmp);
                    else
                      return;
                  }

                  var input: string[] = inputLoad().split('');
                  writerToOutput(this.VigenereCipher(input, chosenAlphabet, passwordLoad("passwordVigener").toLowerCase().split(''), EDswitch));
                }}
              >Vigenère go!</Button>
            </Container>
          </Grid>
        
        <Box marginTop={10}>
          <ExpansionPanel>
            <ExpansionPanelSummary
              id="aboutVigenere"
              expandIcon={<ExpandMoreIcon />}
            >
              <Typography
                color="primary"
                className='heading'
              ><b>ABOUT Vigenère Cipher</b></Typography>
            </ExpansionPanelSummary>
            <ExpansionPanelDetails>
              <Grid container className='columnGrid'>
                <Typography style={{ color: '#808080' }} align='left' component={"div"}>
                  <p>
                    <b>Vigenère cipher</b> is a representative of a family of <i>polyalphabethic substitution ciphers </i>
                    that uses password to define used substitution alphabet from a table known as <i>tabula recta</i>.
                  </p>
                </Typography>

                <Grid container className='columnGrid'>
                  <img
                      src="http://www.stud.feec.vutbr.cz/~xrysav29/cipher_pics/vigenere_encryption.PNG"
                      alt='Vigenère encryption'
                      width="50%"/>
                </Grid>
                <Typography variant='caption' style={{ color: '#808080' }} align='center'>
                  <b>Img 1.:</b> <i>Encryption of plaintext using Vigenère cipher.</i>
                </Typography>

                <Typography style={{ color: '#808080' }} align='left' component={"div"}>
                  <p>
                    Polyalphabetic ciphers use in the process of encryption and decryption more then one substitution alphabet. 
                    Above every element has to be first decided which alphabet to use. Element is afterwards substituted like if a monoalphabetic cipher was used.
                  </p>
                  <p>
                    <i>Tabula recta</i> is a Latin term from 1508, first invented by German monk Johannes Trithemius, that used 
                    this table in his invented cipher 
                    ('<Link color="primary" href="https://www.dcode.fr/trithemius-cipher" target="_blank" rel="noopener noreferrer"><i>Trithemius cipher </i></Link>' - uses successive shifts to the right from 0 to N where N is the length of the text). 
                    Each row of the table consists of alphabet shifted by one position.
                  </p>
                  <div style={{textAlign: "center"}}><this.vigenereDialog /></div>
                </Typography>
              </Grid>
            </ExpansionPanelDetails>
          </ExpansionPanel>
        </Box>
      </div>
    );
  }
}