import React from 'react';
import * as bigrams from './JSON_english_bigram_data.json';
import * as qgrams from './JSON_english_quadrams_data.json';
import { Container, Box, Grid, TextField, Button, Typography, MenuItem, Fab, Switch } from '@material-ui/core';
import BubbleChartTwoToneIcon from '@material-ui/icons/BubbleChartTwoTone';
import BlurOnTwoToneIcon from '@material-ui/icons/BlurOnTwoTone';
import AnalyzerLayout, { atLeastOneChange, inpurOrLanguageChange } from './analyzer/Analyzer';
import CipherTab from './ciphers/CipherTab';


//  GENEREAL CONSTANTS:
const engAlphabet: string[] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
const czeAlphabet: string[] = ['a', 'á', 'b', 'c', 'č', 'd', 'ď', 'e', 'é', 'ě', 'f', 'g', 'h', 'i', 'í', 'j', 'k', 'l', 'm', 'n', 'ň', 'o', 'ó', 'p', 'q', 'r', 'ř', 's', 'š', 't', 'ť', 'u', 'ú', 'ů', 'v', 'w', 'x', 'y', 'ý', 'z', 'ž'];
//  VARIABLES FOR LanguageSettings
export var chosenAlphabet: string[] = engAlphabet;
export var regexp = /\w/g;
export var chosenDatabase: string = 'eng';

//  HASHMAP & ENGLISH BIGRAM DATABASE
export var HashMap = require('hashmap');
export var bigramDatabase: any = new HashMap();
export var qgramDatabase: any = new HashMap();
export var sumOfBiDatabase: number = 0;
export var sumOfQDatabase: number = 0;

// GENEREAL FUNCTIONS:
export function inputLoad(): string {
    return (document.getElementById("inputField") as HTMLInputElement)?.value ?? '';
}

export function writerToOutput(message: string) {
  if (document.getElementById("outputField"))
      (document.getElementById("outputField") as HTMLInputElement).innerHTML = message;
}

export function passwordLoad(fieldId: string): string {
  if (document.getElementById(fieldId)) {
      var inputValue: string[] = (document.getElementById(fieldId) as HTMLInputElement).value.split('');
      var value: string = '';
      inputValue.forEach( e => {
          if(e.match(regexp))
              value += e;
      });
      return value;
  }
  else
      return "";
}

export function scroller() {
  const anchor = document.querySelector('#\\root');
  
  if(anchor) {
    anchor.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }
}

//  CUSTOM ALERT FUNCTION
export function myAlert(message: string, variant: string, ...other: any[]) {
  switch(variant) {
    case 'info':
      alert(message);
      break;
    case 'error':
      console.log(other[0]);
      alert(message);
      break;
    case 'conf':
      var tmp = window.confirm(message);
      if(tmp === false) {
        return false;
      } else
        return true;
    case 'enter':
      var value = window.prompt(message, String(other[0]));
      if (value !== null) {
        if(value !== '')
          return value;
        else
          return String(other[0]);
      } else
        break;
    default:
      alert('An error occured within the myAlert function.');
      return;
  }
}

//  BASIC LAYOUT CLASS + IT'S INTERFACES (props & states)
export interface IbasicLayoutProps {}
export interface IbasicLayoutState {}

export default class basicLayout extends React.Component<IbasicLayoutProps, IbasicLayoutState> {
  private fabSwitch: boolean = false;

  constructor(props: IbasicLayoutProps) {
    super(props);

    this.state = {
    }
    
    //  INIT OF THE BIGRAM AND QGRAM DATABASES
    JSON.parse(JSON.stringify(bigrams), (key: string, value: number) => {
      bigramDatabase.set(key, value);
      if(!isNaN(Number(value)))
        sumOfBiDatabase += value;
    });

    JSON.parse(JSON.stringify(qgrams), (key: string, value: number) => {
      qgramDatabase.set(key, value);
      if(!isNaN(Number(value)))
        sumOfQDatabase += value;
    });

    this.FloatButtons = this.FloatButtons.bind(this);
    this.TextFields = this.TextFields.bind(this);
    this.LanguageSettings = this.LanguageSettings.bind(this);
    this.MenuBar = this.MenuBar.bind(this);
    this.EnDecryptSwitch = this.EnDecryptSwitch.bind(this);
  }

  // LAYOUT OBJECTS:
  private LanguageSettings() {
    const [alphabet, setAlphabet] = React.useState("eng");
    const handleAlphabet = (event: React.ChangeEvent<HTMLInputElement>) => {
      var tmp: boolean = true;
      if(atLeastOneChange)
        tmp = Boolean(myAlert('With alphabet change you\'ll lose ALL achieved data from executed analysis! Proceed?', 'conf'));
      
      if(tmp) {
        setAlphabet(event.target.value);
        (document.getElementById('outputField') as HTMLInputElement).innerText = '';
        this.forceUpdate();
      }
    }
  
    if (alphabet === "eng") {
      chosenAlphabet = engAlphabet;
      regexp = /\w/g;
      chosenDatabase = "eng";
    }
    else if (alphabet === "cze") {
      chosenAlphabet = czeAlphabet;
      regexp = /^[a-zA-ZáčďéěíňóřšťůúýžÁČĎÉĚÍŇÓŘŠŤŮÚÝŽ]/;
      chosenDatabase = "cze";
    }
    else
      myAlert('Something went wrong with alphabet selector!', 'error', alphabet);
  
    return (
        <form noValidate autoComplete="off">
            <div>
              <TextField
                id="alphabetSelector"
                select
                value={alphabet}
                onChange={handleAlphabet}
                label="Alphabet"
                helperText="Please select used alphabet"
                className='choserTextField'
              >
                <MenuItem key={'eng'} value={'eng'}> English Alphabet </MenuItem>
                <MenuItem key={'cze'} value={'cze'}> Czech Alphabet </MenuItem>
              </TextField>
            </div>
        </form>
    );
  }

  private FloatButtons() {
    return(
      <div>
        <Fab id='ciphers' variant='extended' size='large' color='primary'
          style={{
            position: 'fixed',
            float: 'right',
            bottom: 65,
            right: 10,
            zIndex: 9999
          }}
          onClick={() => {
            (document.getElementById('EDSwitch') as HTMLInputElement).disabled = false;
            this.fabSwitch = false;
            this.forceUpdate();
          }}>
          <BlurOnTwoToneIcon />
          <Typography> Ciphers</Typography>
        </Fab>
        <Fab variant='extended' size='large' color='secondary'
          style={{
            position: 'fixed',
            float: 'right',
            bottom: 10,
            right: 10,
            zIndex: 9999
          }}
          onClick={() => {
            (document.getElementById('EDSwitch') as HTMLInputElement).disabled = true;
            this.fabSwitch = true;
            this.forceUpdate();
          }}>
          <BubbleChartTwoToneIcon />
          <Typography> Analyzer</Typography>
        </Fab>
      </div>
    );
  }

  private TextFields() {
    return (
      <div>
        <Grid
          container
          className='rowGrid'
          item={true}
          xs={12}
          spacing={2}
        >
          <Box my={2} marginLeft={3} marginRight={3}>
            <TextField
              id="inputField"
              multiline
              rows="4"
              rowsMax="4"
              variant="outlined"
              defaultValue="Tiger, Tiger, burning bright, in the forest of the night; What immortal hand or eye, could frame thy fearful symmetry?"
              placeholder="Input"
              className='textField'
              onChange={ () => {
                var tmp: boolean = true;
                if(atLeastOneChange)
                  tmp = Boolean(myAlert('With input change you\'ll lose ALL achieved data from executed analysis! Proceed?', 'conf'));
                
                if(tmp) {
                  inpurOrLanguageChange();
                  (document.getElementById('outputField') as HTMLInputElement).innerText = '';
                  this.forceUpdate();
                }
              }}
            />
          </Box>
          
          <Box my={2} marginLeft={3} marginRight={3}>
            <TextField
                id="outputField"
                multiline
                rows="4"
                rowsMax="4"
                variant="outlined"
                placeholder="Output"
                className='textField'
                InputProps={{ readOnly: true }}
              />
          </Box>
        </Grid>
      </div>
    );
  }

  private EnDecryptSwitch() {
    const [state, setState] = React.useState({
      checkedED: false,
    });

    const handleChange = (name: string) => (event: React.ChangeEvent<HTMLInputElement>) => {
      setState({ ...state, [name]: event.target.checked });
      this.forceUpdate();
    };

    return (
      <Box my={3}>
        <Grid container className='columnGrid' alignItems='center'>
          <Typography color='secondary'>ENCRYPTION</Typography>
          <Switch 
            id="EDSwitch"
            color="default"
            checked={state.checkedED}
            onChange={(handleChange('checkedED'))} />
          <Typography color='primary'>DECRYPTION</Typography>
        </Grid>
      </Box>
    );
  }

  private MenuBar() {
    var buttonInable: boolean = false;
    if(this.fabSwitch)
      buttonInable = true;
    
    return(
      <div>
        <Grid container className='rowGrid'>
          <Grid item xs={3}>
            <this.EnDecryptSwitch/>
          </Grid>
          <Grid item xs={3} className='columnGrid'>
            <Box marginTop={3}>
              <Button
                disabled={ buttonInable }
                fullWidth={false}
                variant="outlined"
                style={{backgroundColor: '#ffffff'}}
                onClick={ () => {
                  (document.getElementById("inputField") as HTMLInputElement).value = (document.getElementById("outputField") as HTMLInputElement).value;
                  (document.getElementById("outputField") as HTMLInputElement).innerHTML = "";
                  this.forceUpdate();
              }}><b>Copy Output to Input</b></Button>
            </Box>
            <Box marginBottom={2}>
              <Button
                disabled={ buttonInable }
                fullWidth={false}
                variant="text"
                size="small"
                onClick={ () => {
                  var tmp: boolean = false;
                  tmp = Boolean(myAlert('Do You really want to reset the fields?', 'conf'));
                  if(tmp) {
                    (document.getElementById("inputField") as HTMLInputElement).value = "Tiger, Tiger, burning bright, in the forest of the night; What immortal hand or eye, could frame thy fearful symmetry?";
                    (document.getElementById("outputField") as HTMLInputElement).innerHTML = "";
                  }

                  this.forceUpdate();
              }}><Typography variant='caption'>Reset fields</Typography></Button>
            </Box>
          </Grid>
          <Grid item xs={3}>
            <this.LanguageSettings />
          </Grid>
        </Grid>
      </div>
    );
  }

  public render() {
    var content = () => {
      if(this.fabSwitch)
        return <AnalyzerLayout idInput={"inputField"} idOutput={"outputField"} idSwitch={"EDSwitch"} />
      else
        return <CipherTab idInput={"inputField"} idOutput={"outputField"} idSwitch={"EDSwitch"} />
    }

    return (
      <div>
      <Container maxWidth="lg">
        <Box marginTop={3} marginBottom={8}>
          <this.MenuBar />
          <this.TextFields />
        </Box>
        <Box id='workField'>
          {content}
        </Box>
      </Container>
      
      <this.FloatButtons />
    </div>
    );
  }
}


/*
<p>
    <b>Lorem ipsum</b> dolor sit amet, consectetuer adipiscing elit.
    Quisque porta. Vivamus porttitor turpis ac leo. Etiam neque.
    Cras pede libero, dapibus nec, pretium sit amet, tempor quis.
    Duis condimentum augue id magna semper rutrum.
    Fusce tellus odio, dapibus id fermentum quis, suscipit id erat.
    Nunc tincidunt ante vitae massa.
    Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim.
    Nullam justo enim, consectetuer nec, ullamcorper ac, vestibulum in, elit.
    Et harum quidem rerum facilis est et expedita distinctio.
    Proin mattis lacinia justo. Vivamus ac leo pretium faucibus.
    Aliquam erat volutpat. Quisque tincidunt scelerisque libero.
    Proin mattis lacinia justo. Phasellus faucibus molestie nisl.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
*/