import * as React from "react";

import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import MobileStepper from '@material-ui/core/MobileStepper';
import Button from '@material-ui/core/Button';
import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
import CircularProgress from "@material-ui/core/CircularProgress";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogContentText from "@material-ui/core/DialogContentText";
import DialogTitle from "@material-ui/core/DialogTitle";

import { withRouter } from "react-router-dom";

import VocabularyData from "../components/VocabularyData";

import { IVocab, VocabType } from "../models/vocab";

interface IProps {
    id: string;
    levelVocab: (id: string) => Promise<IVocab[]>;

    history: any;

    stepperIndex: number;
    loading: boolean;
    vocab: IVocab[];
    lookedAt: number[];
    currentVocab: IVocab;
    leaveDialog: boolean;
    reviewDialog: boolean;
    setVocab: (vocab: IVocab[]) => void;
    setLookedAt: (ids: number[]) => void;
    setCurrentVocab: (vocab: IVocab) => void;
    drawerButtonState: (state: boolean) => void;
    setLoading: (state: boolean) => void;
    setStepper: (index: number) => void;
    setReviewDialog: (state: boolean) => void;
    setLeaveDialog: (state: boolean) => void;
};

const LevelPageWithRouter = withRouter(
    class LevelPage extends React.Component<IProps> {
        private uid = 0;
        // To prevent React from redrawing the vocabulary list and prematurely
        // cancelling the animation
        private uids: { [key: string]: string } = {};

        componentDidMount() {
            // Hide the drawer
            this.props.drawerButtonState(false);

            // Fetch the vocabulary
            this.props.setLoading(true);

            // TODO: Error handling
            this.props.levelVocab(this.props.id).then(vocab => {
                this.props.setVocab(vocab);
                this.props.setCurrentVocab(vocab[0]);
                this.props.setLookedAt([vocab[0].id]);
                this.props.setStepper(0);
                this.props.setLoading(false);
            });
        }

        genUID = (vocab: IVocab): string => {
            const { grundform } = vocab.latin;
            if (grundform in this.uids) {
                return this.uids[grundform];
            } else {
                this.uids[grundform] = "LEVELPAGE" + this.uid++;
                return this.uids[grundform];
            }
        }

        toReview = () => {
            this.props.setLoading(true);
            this.props.setStepper(0);
            this.props.history.push(`/review/level/${this.props.id}`);
        }

        openReview = () => {
            this.props.setReviewDialog(true);
        }
        closeReview = () => {
            this.props.setReviewDialog(false);
        }

        openLeave = () => {
            this.props.setLeaveDialog(true);
        }
        closeLeave = () => {
            this.props.setLeaveDialog(false);
        }

        cancelLevel = () => {
            this.closeLeave();
            this.props.history.push("/dashboard");
        }

        nextVocab = () => {
            // Get the next vocab item
            const { stepperIndex, vocab } = this.props;

            // When we are about to go out of bounds, then we want to
            // ask whether the user wants to review
            if (stepperIndex + 1 >= vocab.length) {
                this.openReview();
            } else {
                const newVocab = vocab[stepperIndex + 1];

                // Set the stepperIndex and the currentVocab
                this.props.setStepper(stepperIndex + 1);
                this.props.setCurrentVocab(newVocab);
            }
        }

        prevVocab = () => {
            // Get the next vocab item
            const { stepperIndex, vocab } = this.props;

            // Prevent going out of bounds
            if (stepperIndex - 1 < 0) {
                this.openLeave();
            } else {
                const newVocab = vocab[stepperIndex - 1];

                // Set the stepperIndex and the currentVocab
                this.props.setStepper(stepperIndex - 1);
                this.props.setCurrentVocab(newVocab);
            }
        }

        render() {
            if (this.props.loading) {
                return <div>
                    <Grid
                        container
                        spacing={0}
                        direction="column"
                        alignItems="center"
                        justify="center"
                        style={{ minHeight: '100vh' }}>
                        <Grid item xs={12}>
                            <Paper className="paper">
                                <Grid container direction="column" spacing={8}>
                                    <CircularProgress />
                                </Grid>
                            </Paper>
                        </Grid>
                    </Grid>

                </div>;
            }

            const vocabTypeToStr = {
                [VocabType.NOMEN]: "Nomen",
                [VocabType.VERB]: "Verb",
                [VocabType.ADJEKTIV]: "Adjektiv",
                [VocabType.ADVERB]: "Adverb",
            };
            const { currentVocab, vocab, stepperIndex } = this.props;
            return <div>
                <Grid container justify="center">
                    <Grid item>
                        <Grid container direction="column">
                            <Grid item className="level-card">
                                <Card
                                    square={true}
                                    style={{ margin: 12 }}>
                                    <CardContent>
                                        <Typography gutterBottom variant="headline" component="h2">
                                            {`${currentVocab.latin.grundform} (${vocabTypeToStr[currentVocab.type]})`}
                                        </Typography>
                                        <VocabularyData vocab={currentVocab} />
                                    </CardContent>
                                </Card>
                            </Grid>
                        </Grid>

                    </Grid>
                </Grid>
                <MobileStepper
                    steps={vocab.length + 1}
                    position="static"
                    activeStep={stepperIndex}
                    className="level-stepper"
                    nextButton={
                        <Button
                            onClick={this.nextVocab}
                            disabled={stepperIndex >= vocab.length + 1}>
                            <KeyboardArrowRight />
                            Nächste
                        </Button>
                    }
                    backButton={
                        <Button onClick={this.prevVocab}>
                            <KeyboardArrowLeft />
                            {
                                stepperIndex === 0 ? (
                                    `Abbrechen`
                                ) : (
                                        `Zurück`
                                    )
                            }
                        </Button>
                    } />

                {/*The leave and the "to review" dialog*/}
                <Dialog
                    open={this.props.reviewDialog}
                    onClose={this.closeReview}>
                    <DialogTitle>Willst du zur Übung?</DialogTitle>
                    <DialogActions>
                        <Button
                            onClick={this.toReview}>
                            Zur Übung
                        </Button>
                        <Button
                            onClick={this.closeReview}>
                            Noch nicht
                        </Button>
                    </DialogActions>
                </Dialog>
                <Dialog
                    open={this.props.leaveDialog}
                    onClose={this.closeLeave}>
                    <DialogTitle>Willst du das Level abbrechen?</DialogTitle>
                    <DialogContent>
                        <DialogContentText>
                            Wenn du jetzt abbricht, dann geht dein Fortschritt
                            in diesem Level verloren.
                        </DialogContentText>
                    </DialogContent>
                    <DialogActions>
                        <Button
                            onClick={this.closeLeave}>
                            Zurück zum Level
                        </Button>
                        <Button
                            onClick={this.cancelLevel}>
                            Level abbrechen
                        </Button>
                    </DialogActions>
                </Dialog>
            </div>;
        }
    }
);
export default LevelPageWithRouter;
