import * as React from "react";

import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import IconButton from "@material-ui/core/IconButton";
import SwipeableDrawer from "@material-ui/core/SwipeableDrawer";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import Divider from "@material-ui/core/Divider";
import Avatar from "@material-ui/core/Avatar";
import MenuIcon from "@material-ui/icons/Menu";
import SettingsIcon from "@material-ui/icons/Settings";
import PersonIcon from "@material-ui/icons/Person";
import InfoIcon from "@material-ui/icons/Info";
import HomeIcon from "@material-ui/icons/Home";
import BookIcon from "@material-ui/icons/Book";
import ViewWeekIcon from "@material-ui/icons/ViewWeek";

import { BrowserRouter, Route, Redirect, Link } from "react-router-dom";

import AuthRoute from "../security/AuthRoute";

import Dashboard from "../pages/dashboard";
import LoginPage from "../pages/login";
import LevelListPage from "../pages/levelList";
import LevelPage from "../pages/level";
import ReviewPage from "../pages/review";
import SummaryPage from "../pages/summary";
import WelcomePage from "../pages/intro";

import { ILevel } from "../models/level";
import { ILearner } from "../models/learner";
import { IVocab, VocabType } from "../models/vocab";
import { IReviewMetadata, ReviewType } from "../models/review";

interface IState {
    loggedIn: boolean;

    lastReview: IReviewMetadata;

    drawerOpen: boolean;
    showDrawerButton: boolean;
}

// TODO: Replace the sessionStorage with localStorage?
// TODO: Cache API-Calls
export default class Application extends React.Component<{}, IState> {
    constructor(props: any) {
        super(props);

        // Load a key from the SessionStorage
        const authKey = window.sessionStorage.getItem("authKey") || null;
        // TODO
        const loggedIn = authKey !== null;

        // TODO: Fetch the last review
        this.state = {
            loggedIn,

            lastReview: {
                correct: 0,
                wrong: 0,
            },

            drawerOpen: false,
            showDrawerButton: true,
        };

        this.login = this.login.bind(this);
        this.isAuthenticated = this.isAuthenticated.bind(this);
    }

    getLevels(): ILevel[] {
        console.log("STUB: Application::getLevels");
        // TODO: Actually fetch them from somewhere
        const levels = [{
            name: "Der Bauer auf dem Feld",
            desc: "So fängt alles an: Du bist ein einfacher Bauer und musst dich die Karriereleiter mit deinen freshen Latein-Skills hinaufarbeiten",
            level: 1,
            done: true,
        }, {
            name: "???",
            desc: "Warum schreibe ich überhaupt was?dsd dddddddddddddddddddddd",
            level: 2,
            done: false,
        }];

        return levels;
    }

    getLastReview = (): IReviewMetadata => {
        console.log("STUB: Application::getLastReview");

        // TODO: Actually fetch this
        return this.state.lastReview;
    }

    setLastReview = (meta: IReviewMetadata) => {
        // TODO: Send this to the server
        this.setState({
            lastReview: meta,
        });
    }

    getReviewQueue = (): IVocab[] => {
        console.log("STUB: Application::getReviewQueue");

        // TODO: Implement
        return [{
            german: ["Wein"],
            hint: "Worte auf '-um' sind meistens NeutrUM",
            type: VocabType.NOMEN,
            latin: {
                grundform: "Vinum",
                genitiv: "Vini",
                genus: "Neutrum"
            },
            id: 0
        }/* , {
          *    latin: "Vici",
          *    german: "<Wortbedeutung>",
          *    hint: "Wird \"Viki\" und nicht \"Vichi\" ausgesprochen",
          *    mnemonic: "Merk dir das Wort mit Caesars berühmten Worten: \"Veni Vidi Vici\"; Er kam, sah und siegte",
          *    type: VocabType.NOMEN,
          *    id: 2
            }, {
          *    latin: "fuga",
          *    german: "Flucht",
          *    hint: "Worte auf \"-a\" sind FeminA",
          *    type: VocabType.NOMEN,
          *    id: 3
            } */] as IVocab[];
    }

    getLearners(): ILearner[] {
        console.log("STUB: Application::getLearners");

        // TODO: Implement
        return [{
            username: "Polynomdivision",
            level: 5,
            score: 400,
        }, {
            username: "Polynomdivision2",
            level: 3,
            score: 500,
        }, {
            username: "Der eine Typ",
            level: 7,
            score: 100,
        }];
    }

    getTopTenLearners(): ILearner[] {
        console.log("STUB: Application::getTopTenLearners");

        // TODO: Implement
        return [{
            username: "Polynomdivision",
            level: 5,
            score: 400,
        }, {
            username: "Polynomdivision2",
            level: 3,
            score: 500,
        }, {
            username: "Der eine Typ",
            level: 7,
            score: 100,
        }];
    }

    getNextLevel(): ILevel {
        console.log("STUB: Application::getNextLevel");

        // TODO: Actually fetch data
        return {
            name: "???",
            desc: "Warum schreibe ich überhaupt was?dsd dddddddddddddddddddddd",
            level: 2,
            done: false,
        };
    }

    getLevelVocab(id: number): IVocab[] {
        console.log("STUB: Application::getLevelVocab");

        // TODO: Actually implement this
        // TODO: Don't fetch this when it was already fetched once.
        return [{
            german: ["Wein"],
            hint: "Worte auf '-um' sind meistens NeutrUM",
            type: VocabType.NOMEN,
            latin: {
                grundform: "Vinum",
                genitiv: "Vini",
                genus: "Neutrum"
            },
            id: 0
        }/* , {
          *    latin: "Vici",
          *    german: "<Wortbedeutung>",
          *    hint: "Wird \"Viki\" und nicht \"Vichi\" ausgesprochen",
          *    mnemonic: "Merk dir das Wort mit Caesars berühmten Worten: \"Veni Vidi Vici\"; Er kam, sah und siegte",
          *    type: VocabType.NOMEN,
          *    id: 2
            }, {
          *    latin: "fuga",
          *    german: "Flucht",
          *    hint: "Worte auf \"-a\" sind FeminA",
          *    type: VocabType.NOMEN,
          *    id: 3
            } */] as IVocab[];
    }

    login(username: string, password: string): Promise<boolean> {
        console.log("STUB: Application::login");

        return new Promise((res, rej) => {
            // TODO: First login? Redirect to /welcome
            // TODO
            this.setState({
                loggedIn: true
            });
            res();
        });
    }

    // Checks whether the user is logged in
    isAuthenticated() {
        // TODO: Security?
        return this.state.loggedIn === true;
    }

    closeDrawer = () => {
        this.setState({
            drawerOpen: false,
        });
    }

    drawerButtonState = (show: boolean) => {
        // This is required as we would otherwise try to continously update
        // the state, resulting in an infinte loop
        if (show !== this.state.showDrawerButton) {
            this.setState({
                showDrawerButton: show,
            });
        }
    }

    render() {
        return <BrowserRouter
            basename="/app/">
            <div className="flex">
                <AppBar position="static">
                    <Toolbar>
                        {
                            (this.isAuthenticated() && this.state.showDrawerButton) ? (
                                <IconButton
                                    color="inherit"
                                    onClick={() => this.setState({ drawerOpen: true })}>
                                    <MenuIcon />
                                </IconButton>
                            ) : undefined
                        }
                        <Typography className="flex" variant="title" color="inherit">
                            Lateinicus
                        </Typography>
                    </Toolbar>
                </AppBar>
                <SwipeableDrawer
                    anchor="left"
                    open={this.state.drawerOpen}
                    onClose={() => this.setState({ drawerOpen: false, })}
                    onOpen={() => this.setState({ drawerOpen: true })}>
                    <List component="nav">
                        <ListItem>
                            {/* TODO: Replace with the actual username */}
                            <Avatar alt="{Username}" style={{ width: 80, height: 80 }} src="https://avatarfiles.alphacoders.com/105/105250.jpg" />
                            <ListItemText primary="{Username}" />
                        </ListItem>

                        <Divider />

                        <ListItem button>
                            <ListItemIcon>
                                <PersonIcon />
                            </ListItemIcon>
                            <ListItemText primary="Profil" />
                        </ListItem>
                        <ListItem button>
                            <ListItemIcon>
                                <SettingsIcon />
                            </ListItemIcon>
                            <ListItemText primary="Einstellungen" />
                        </ListItem>

                        <Divider />

                        <ListItem
                            component={Link}
                            to="/dashboard"
                            onClick={this.closeDrawer}
                            button>
                            <ListItemIcon>
                                <HomeIcon />
                            </ListItemIcon>
                            <ListItemText primary="Dashboard" />
                        </ListItem>
                        <ListItem
                            component={Link}
                            to="/review/queue"
                            onClick={this.closeDrawer}
                            button>
                            <ListItemIcon>
                                <BookIcon />
                            </ListItemIcon>
                            <ListItemText primary="Widerholen" />
                        </ListItem>
                        <ListItem
                            component={Link}
                            to="/levelList"
                            onClick={this.closeDrawer}
                            button>
                            <ListItemIcon>
                                <ViewWeekIcon />
                            </ListItemIcon>
                            <ListItemText>
                                Levelübersicht
                            </ListItemText>
                        </ListItem>

                        <Divider />

                        <ListItem button onClick={() => {
                            // Remove the auth token from the SessionStorage
                            window.sessionStorage.removeItem("authKey");
                            // Set the loggedIn State to false
                            this.setState({
                                loggedIn: false,
                                // In case the drawer was open
                                drawerOpen: false,
                            });
                        }}>
                            <ListItemText>
                                Abmelden
                            </ListItemText>
                        </ListItem>

                        <Divider />

                        <ListItem button onClick={() => window.location = "https://gitlab.com/Polynomdivision/Lateinicus/tree/master"}>
                            <ListItemIcon>
                                <InfoIcon />
                            </ListItemIcon>
                            <ListItemText primary="Über" />
                        </ListItem>
                    </List>
                </SwipeableDrawer>

                <div className="content">
                    <Route exact path="/" component={() => <Redirect to="/login" />} />
                    <Route exact path="/login" component={() => {
                        return <LoginPage loggedIn={this.state.loggedIn} login={this.login} />
                    }} />
                    <AuthRoute
                        isAuth={this.isAuthenticated}
                        path="/dashboard"
                        component={() => {
                            return <Dashboard
                                nextLevel={this.getNextLevel}
                                getLastReview={this.getLastReview}
                                getTopTen={this.getTopTenLearners} />
                        }} />
                    <AuthRoute
                        isAuth={this.isAuthenticated}
                        path="/welcome"
                        component={() => {
                            return <WelcomePage />
                        }} />
                    <AuthRoute
                        isAuth={this.isAuthenticated}
                        path="/levelList"
                        component={() => <LevelListPage
                            levels={this.getLevels()} />} />
                    {/*We cannot use AuthRoute here, because match is undefined otherwise*/}
                    <Route
                        path="/level/:id"
                        component={({ match }) => {
                            if (this.isAuthenticated()) {
                                return <LevelPage
                                    id={match.params.id}
                                    levelVocab={this.getLevelVocab}
                                    drawerButtonState={this.drawerButtonState}
                                    setLastReview={this.setLastReview} />;
                            } else {
                                return <Redirect to="/login" />;
                            }
                        }} />
                    <Route
                        path="/review/level/:id"
                        component={({ match }) => {
                            if (this.isAuthenticated()) {
                                return <ReviewPage
                                    reviewType={ReviewType.LEVEL}
                                    levelId={match.params.id}
                                    vocabByLevel={this.getLevelVocab}
                                    drawerButtonState={this.drawerButtonState}
                                    setLastReview={this.setLastReview} />;
                            } else {
                                return <Redirect to="/login" />;
                            }
                        }} />
                    <AuthRoute
                        isAuth={this.isAuthenticated}
                        path="/review/queue"
                        component={() => {
                            return <ReviewPage
                                reviewType={ReviewType.QUEUE}
                                vocabByQueue={this.getReviewQueue}
                                drawerButtonState={this.drawerButtonState}
                                setLastReview={this.setLastReview} />;
                        }} />
                    <AuthRoute
                        isAuth={this.isAuthenticated}
                        path="/review/summary"
                        component={() => {
                            return <SummaryPage
                                reviewMeta={this.getLastReview} />
                        }} />
                </div>
            </div>
        </BrowserRouter>;
    }
};
