import { Component, ElementRef, NgZone, OnInit, ViewChild, ViewChildren } from '@angular/core';
import { IgxRadioComponent, IgxRadioGroupDirective } from 'igniteui-angular';
import { Observable, Subject } from 'rxjs';
import { Answer, Card, DbService, Question, Saved } from '../db.service';
import { UserdataService } from '../userdata.service';


@Component({
    selector: 'app-minigame-biotrivia',
    templateUrl: './minigame-biotrivia.component.html',
    styleUrls: ['./minigame-biotrivia.component.scss']
})
export class MinigameBiotriviaComponent implements OnInit {
    @ViewChildren('startDialog') startingElementRef;
    @ViewChildren('ongoingDialog') ongoingElementRef;
    @ViewChildren('endDialog') endingElementRef;

    stage: 'starting' | 'starting-ongoing' | 'ongoing' | 'ongoing-ended' | 'ended' = 'starting';

    questions: Question[];

    displayError = false;

    guessedQuestions = 0;
    currQuestionN = 0;
    currQuestion: Question;
    currAnswers: string[];

    wonCard: Card = null;

    answers: Array<{ question: Question, answer: string }> = [];

    selectedAnswer = '';
    isAnswered(): boolean {
        return this.selectedAnswer !== '';
    }

    constructor(
        private db: DbService,
        private userdata: UserdataService,
    ) { }

    ngOnInit(): void {
    }

    endGame(): void {
        this.stage = 'ongoing-ended';

        const successRate = (this.guessedQuestions) / this.questions.length;

        if (successRate > 0.5) {
            const owned = this.userdata.getOwnedCardIds();

            let newCard = null;

            do {
                newCard = this.db.getRandomCardId(successRate - .5);
            } while (owned.includes(newCard));

            this.userdata.addCard(newCard);
            this.wonCard = this.db.getCard(newCard);
        }

        setTimeout(() => {
            this.endingElementRef.first.nativeElement.style.opacity = 0;
            this.animateElements(
                this.ongoingElementRef.first.nativeElement,
                this.endingElementRef.first.nativeElement
            // tslint:disable-next-line: deprecation
            ).subscribe(() => {
                this.stage = 'ended';
            });
        }, 10);
    }

    submitAnswer(): void {
        if (!this.isAnswered()) {
            this.displayError = true;
            return;
        }
        this.ongoingElementRef.first.nativeElement.style.position = 'absolute';

        if (this.selectedAnswer === this.currQuestion.answer.correctChoise) this.guessedQuestions++;

        this.answers.push({
            answer: this.selectedAnswer,
            question: this.currQuestion,
        });

        if (this.currQuestionN >= this.questions.length) {
            this.endGame();
            return;
        }

        this.displayError = false;
        this.selectedAnswer = '';
        this.loadNextQuestion();
    }

    animateElements(el1: HTMLElement, el2: HTMLElement): Observable<void> {
        const a = new Subject<void>();
        el1.style.position = 'absolute';
        el1.animate([
            {
                transform: 'translateX(0)',
                opacity: 1,
            },
            {
                transform: 'translateX(-100vh)',
                opacity: 0,
            },
        ], {
            duration: 200,
            easing: 'ease-in',
        }).onfinish = () => {
            el1.style.opacity = '0';
        };
        el2.animate([
            {
                transform: 'translateX(100vh)',
                opacity: 0,
            },
            {
                transform: 'translateX(0)',
                opacity: 1,
            },
        ], {
            duration: 200,
            easing: 'ease-out',
        }).onfinish = () => {
            el2.style.opacity = '1';
            a.next();
        };
        return a;
    }

    loadQuestion(i: number): void {
        this.currQuestion = this.questions[i];
        this.currAnswers = this.shuffle(this.questions[i].answer.choises);
    }
    loadNextQuestion(): void {
        this.loadQuestion(this.currQuestionN++);
    }

    startGame(): void {
        if (this.stage !== 'starting') return;

        const startingEl = this.startingElementRef.first.nativeElement as HTMLElement;
        startingEl.style.position = 'absolute';

        this.stage = 'starting-ongoing';
        this.questions = this.db.getRandomQuestions(1);
        this.loadNextQuestion();

        setTimeout(() => {
            const ongoingEl = this.ongoingElementRef.first.nativeElement as HTMLElement;

            // tslint:disable-next-line: deprecation
            this.animateElements(startingEl, ongoingEl).subscribe(() => {
                this.stage = 'ongoing';
            });
        }, 20);
    }

    shuffle<T>(array: T[]): T[] {
        let currentIndex = array.length;
        let temporaryValue;
        let randomIndex;

        // While there remain elements to shuffle...
        while (0 !== currentIndex) {

            // Pick a remaining element...
            randomIndex = Math.floor(Math.random() * currentIndex);
            currentIndex -= 1;

            // And swap it with the current element.
            temporaryValue = array[currentIndex];
            array[currentIndex] = array[randomIndex];
            array[randomIndex] = temporaryValue;
        }

        return array;
    }

    getIncorrectAnswers(): { question: Question, answer: string, index: number }[] {
        return this.answers.map((v, i) => {
            return { ...v, index: i + 1 };
        }).filter((v) => v.answer !== v.question.answer.correctChoise);
    }

    restartGame(): void {
        if (this.stage !== 'ended') return;

        const endingEl = this.endingElementRef.first.nativeElement as HTMLElement;
        endingEl.style.position = 'absolute';

        this.stage = 'ongoing-ended';

        this.questions = this.db.getRandomQuestions(1);

        this.displayError = false;

        this.guessedQuestions = 0;
        this.currQuestionN = 0;
        this.answers = [];

        this.selectedAnswer = '';

        this.wonCard = null;

        this.loadNextQuestion();

        setTimeout(() => {
            const ongoingEl = this.ongoingElementRef.first.nativeElement as HTMLElement;

            // tslint:disable-next-line: deprecation
            this.animateElements(endingEl, ongoingEl).subscribe(() => {
                this.stage = 'ongoing';
            });
        }, 20);
    }
}
