import { Component, EventEmitter, HostListener, Injectable, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable, Subject } from 'rxjs';
import { Subscription } from 'rxjs';
import { first, map, take } from 'rxjs/operators';
import { ICrudService } from './services/crudServices/crud.service';
import { StateService } from './services/state.service';
@Injectable()
// @Component({
//     template: ''
// })
export abstract class ScreenBase<T> implements OnInit, OnDestroy {
    private _screenSaveDoneSubscription: Subscription;
    protected wasWaitingForDependency: boolean = false;
    protected refndx: string;
    protected linkPath: string;
    protected screenUpdateWaitList: string[] = undefined;
    /**
     * Current screen, will set to state service after `screenOnInit()`
     */
    protected screen: string;

    /**
     * Current screen with shared screen lock id like: A71S and A71SC
     */
    protected sharedScreenId: string = null;
    protected subscriptions: Subscription[] = [];
    protected lockScreen: boolean = true;
    protected allData: T[] = [];;
    //constants = Constants;
    //screenInfo: NavigatorItem;
    @Input() isSnapshotView: boolean = false;

    @Input() isLoading: boolean = true;
    @Input() isScreen: boolean = true;

    @Input() readonly: boolean = false;
    @Input() isProcessing: boolean = false;
    @Output() screenSaveDone = new EventEmitter<any>();
    constructor(
        protected crudService: ICrudService<T>,
        protected stateService: StateService,
        protected route: ActivatedRoute,
    ) { }

    ngOnInit(): void {
        if (false == this.isSnapshotView) {
            //   this.subscriptions.push(this.stateService.saveSubject.subscribe({ next: () => this.save() }));
            //   this.subscriptions.push(this.stateService.cancelSubject.subscribe({ next: () => this.cancel() }));

            this.route.url
                .pipe(take(1))
                .subscribe(url => {
                    this.linkPath = url[0].path.toLowerCase();

                    this.screenOnInit();


                    //this.screenInfo = this.stateService.treeListService.screenSEQ.find(n => n.screen == this.screen);
                    //Doing Security at here

                    if (false == this.isSnapshotView) {

                        this.runGetAllData();

                    }
                });
        }
        else {
            this.initializeForSnapshot();
        }
    }


    ngOnDestroy(): void {
        this.subscriptions.forEach(subscription => { if (subscription) subscription.unsubscribe(); });
    }
    protected runGetAllData() {

        this.isLoading = true;
        this.getAllData().pipe(first()).subscribe(result => {
            this.isLoading = false;
            this.allData = result;
            this.allDataLoaded();
        });
    }
    /**
     * after get refndx from state service, and will be called when refndx changed.
     */
    abstract screenOnInit(): void;


    /**
     * will be called when saving triggered by user or system.
     */
    save(): ScreenSavingRef {
        let saveRef = new ScreenSavingRef();
        if (this.saveMethod != null) {
            this.beforeSave().pipe(first()).subscribe(result => {
                if (result) {

                    this.saveMethod.pipe(first()).subscribe(result => {
                        saveRef.saveDone(result);
                        this.saveDone();
                        this.screenSaveDone.next(result);
                    });
                }
            });
        } else {
            saveRef.onSaveDone = Observable.of(false);
        }
        return saveRef;

    };

    /**
     * save method for send saving request to api
     */
    abstract get saveMethod(): Observable<any>;

    /**
     * will be called when screen id and refndx initialized or user click cancel button.     */


    protected getAllData() {
        this.isLoading = true;
        return this.crudService.getAll();
    }
    /**
     * will be called when canceling triggered by user or system.
     */
    cancel(): void {
        this.runGetAllData();
    };

    saveDone(): void {
        //do something after saving
        //update screen history

        //alert(`Save Done: do something after ${this.screen} saving`);
    }


    /**
     * will be called on `ngOnInit` if `isSnapshotView==true`
     *    */
    protected initializeForSnapshot(): void {

    }

    /**
     * will be called after `runGetAllData`
     *    */
    protected allDataLoaded(): void {

    }

    /**
     * will be called when deactivated, Default as `Observable.of(true)`
     *    */
    protected beforeLeaveScreen(): Observable<boolean> {
        return Observable.of(true);
    }

    /**
     * will be called before saving, Default as `Observable.of(true)`
     *    */
    protected beforeSave(): Observable<boolean> {
        return Observable.of(true);
    }


    canDeactivate(): Observable<boolean> | boolean {
        return this.beforeLeaveScreen().pipe(map(response => {
            if (response) {
                return true;
            }
            return false;
        }));
    }


}

export class ScreenSavingRef {
    protected onSaveDone$: Subject<any> = new Subject();
    onSaveDone: Observable<any> = this.onSaveDone$.asObservable();

    saveDone(res?: any) {
        this.onSaveDone$.next(res);
        this.onSaveDone$.complete();
    }
}