import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { RouterExtensions } from '@nativescript/angular';
import { SwipeDirection, SwipeGestureEventData } from '@nativescript/core/ui/gestures';
import { Select, Store } from '@ngxs/store';
import { Feedback, FeedbackType } from 'nativescript-feedback';
import { Observable } from 'rxjs';
import { AuthGuard } from '~/core/services/auth-guard.service';
import { EvaluationSurvey } from '../../entities/evaluation-survey';
import { EvaluationAnswerPerson } from '../../entities/input/personUpdate';
import { EvaluationAnswerAllOutput } from '../../entities/output/evaluationAnswersOutput';
import { AnswersIndividualState } from '../../state-mgmt/evaluation-answers-individual.state';
import { UpdateIndivEvaluation } from '../../state-mgmt/evaluation-person-update.actions';
import { UpdateIndivEvaluationState } from '../../state-mgmt/evaluation-person-update.state';

@Component({
    selector: 'EvaluationAnswers',
    moduleId: module.id,
    templateUrl: './evaluation-answers.component.html',
    styleUrls: ['./evaluation-answers.component.scss']
})

export class EvaluationAnswersComponent implements OnInit {

    @Select(AnswersIndividualState.getAnswers) answers$: Observable<EvaluationAnswerAllOutput[]>;
    @Select(AnswersIndividualState.isLoading) answersIsLoading$: Observable<boolean>;
    @Select(AnswersIndividualState.getIDEvalPerson) idEvalPerson$: Observable<number>;
    @Select(UpdateIndivEvaluationState.getError) error$: Observable<String>;

    @Select(UpdateIndivEvaluationState.isLoading) updateIsLoading$: Observable<boolean>;

    @ViewChild('scroller', {static: false}) scrollView: ElementRef;

    survey: EvaluationSurvey;
    checkProp: boolean = true;
    error: String = '';

    constructor(
        private routerExtensions: RouterExtensions,
        private store: Store,
        private authGuard: AuthGuard
    ) {}

    ngOnInit(): void {
        // We don't have to wait, because answeres are already loaded
        // Small timeout is set to load css styling of survey properly
        setTimeout(() => {
            this.answers$.subscribe(answersInput => this.survey = new EvaluationSurvey(answersInput));
        }, 10);
    }

    // Shows error or action confirmation on top of the screen
    showFeedback(title: string, type: FeedbackType, message: string): void {
        new Feedback().show({
            title,
            type,
            duration: 5000,
            message
        });
    }

    // Question tapped
    onRadioTap(answer: EvaluationAnswerAllOutput, tappedIndex: number): void {
        answer.radioOptions.click(tappedIndex);
    }

    // Question reset button
    onReset(answer: EvaluationAnswerAllOutput): void {
        answer.radioOptions.reset();
    }

    // Load previous page of survey
    onPrevPage(): void {
        this.authGuard.canActivate();
        this.survey.prevSet();
        this.pageChanged();
    }

    // Load next page of survey
    onNextPage(): void {
        this.authGuard.canActivate();
        this.survey.nextSet();
        this.pageChanged();
    }

    // Saving survey
    onSave(): void {
        this.authGuard.canActivate();

        const answers = [];

        this.survey.answers.forEach(answer => {
            answers.push(new EvaluationAnswerPerson(answer.ID_EvaluationCriteria, answer.radioOptions.answer));
        });
        this.idEvalPerson$.subscribe(id => this.store.dispatch(new UpdateIndivEvaluation(id, answers)));

        // Limits in ms
        const oneCallLimit = 50; // 50 ms
        const wholeOperationLimit = 7000; // 7 sec

        const operationTimer = setTimeout(() => {
            clearInterval(updateInterval);
            this.showFeedback('Vypršel timeout', FeedbackType.Error, 'Časový limit pro operaci vypršel.');
        }, wholeOperationLimit);

        const updateInterval = setInterval(() => {
            let updateIsLoading;
            this.updateIsLoading$.subscribe(loading => updateIsLoading = loading);

            if (!updateIsLoading) {
                this.error$.subscribe(err => this.error = err);

                if (!this.error) {
                    this.showFeedback('Operace proběhla úspěšně', FeedbackType.Success, 'Dotazník byl úspěšně uložen.');
                } else {
                    this.showFeedback('Operace selhala', FeedbackType.Error, 'Zkontrolujte připojení k internetu.');
                }

                clearInterval(updateInterval);
                clearTimeout(operationTimer);
            }
        }, oneCallLimit);
    }

    // Back button action
    onBackButton(): void {
        this.routerExtensions.back();
    }

    // Swipe event - same as buttons: left swipe loads next page, right swipe loads previous page
    onSwipe(args: SwipeGestureEventData): void {
        if (args.direction === SwipeDirection.left && !this.survey.isLastPage()) {
            this.onNextPage();
        }
        if (args.direction === SwipeDirection.right && !this.survey.isFirstPage()) {
            this.onPrevPage();
        }
    }

    // Scroll to top on page change
    pageChanged(): void {
        const view = this.scrollView.nativeElement;
        view.scrollToVerticalOffset(0, false);
    }
}
