import {
    Component,
    OnInit,
    OnChanges,
    OnDestroy,
    Input,
    Output,
    EventEmitter,
    ViewChild,
    ElementRef,
    ChangeDetectorRef,
    ChangeDetectionStrategy,
    Renderer2,
    AfterViewChecked,
} from '@angular/core';
import { FormGroup } from '@angular/forms';
// import {Observable} from 'rxjs';
import { trigger, state, style, animate, transition } from '@angular/animations';
import { SessionService, LAYOUT_TYPE, STYLE_TYPE, CustomizationService } from '@pepperi/lib';

@Component({
    selector: 'pepperi-quantity-selector',
    templateUrl: './quantity-selector.component.html',
    styleUrls: ['./quantity-selector.component.scss'],
    changeDetection: ChangeDetectionStrategy.OnPush,
    animations: [
        trigger('showHide', [
            state(
                'show',
                style({
                    opacity: 1,
                    transform: 'scale(1)',
                })
            ),
            state(
                'hide',
                style({
                    opacity: 0,
                    transform: 'scale(0)',
                })
            ),
            transition('show => hide', animate('250ms ease-out')),
            transition('hide => show', animate('250ms ease-in')),
        ]),
    ],
})
export class PepperiQuantitySelectorComponent implements OnChanges, OnInit, AfterViewChecked, OnDestroy {
    public static ENTER_CHILDREN = '[EnterChildren]';
    public static ENTER_PACKAGE = '[EnterPackage]';

    @Input() key: string = '';
    @Input() value: string = '';
    @Input() formattedValue: string = '';
    @Input() label: string = '';
    @Input() type: string = 'qs';
    @Input() required: boolean = false;
    @Input() disabled: boolean = false;
    @Input() readonly: boolean = false;
    @Input() textColor: string = '';
    @Input() xAlignment: string = '0';
    @Input() rowSpan: number = 1;
    @Input() lastFocusField: any;
    @Input() alowDecimal: boolean = false;
    @Input() additionalValue: string = '';
    @Input() notificationInfo: any;

    controlType = 'qs';

    @Input() form: FormGroup = null;
    @Input() showTitle: boolean = true;
    @Input() layoutType: LAYOUT_TYPE = LAYOUT_TYPE.PepperiForm;
    @Input() isActive: boolean = false;
    @Input() showQSButtons = true;

    @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>();
    @Output() elementClicked: EventEmitter<any> = new EventEmitter<any>();

    @ViewChild('QSCont') QSCont: ElementRef;
    @ViewChild('QSInput') QSInput: ElementRef;

    LAYOUT_TYPE = LAYOUT_TYPE;
    standAlone = false;
    isFocus: boolean = false;
    isMatrixFocus: boolean = false;

    isCaution = false;
    messages: Array<any> = null;
    showQsBtn = false;
    resize: any;

    sameElementInTheWantedRow = null;
    STYLE_TYPE = STYLE_TYPE;
    styleClass = STYLE_TYPE.Strong;
    isEmptyKey = false;

    constructor(
        private cd: ChangeDetectorRef,
        private customizationService: CustomizationService,
        public sessionService: SessionService,
        private renderer: Renderer2,
        public _eref: ElementRef
    ) { }

    ngOnInit() {
        if (this.form === null) {
            if (this.key === '') {
                this.isEmptyKey = true;
            }

            this.standAlone = true;
            this.form = this.customizationService.getDefaultFromGroup(this.key, this.value, this.required, this.readonly, this.disabled);
            this.formattedValue = this.formattedValue || this.value;

            this.renderer.addClass(this._eref.nativeElement, CustomizationService.STAND_ALONE_FIELD_CLASS_NAME);
        }

        const self = this;
        this.setQsView();
        // TODO:
        // this.resize = Observable.fromEvent(window, 'resize')
        //     .debounceTime(100)
        //     .subscribe((event) => {
        //         self.setQsView();
        //     });
    }

    ngAfterViewChecked() {
        setTimeout(() => {
            this.setQsView();
        }, 125);
    }

    ngOnChanges(changes: any) {
        // Bug fix for addons when the key is '' in the ngOnInit for some reson
        if (this.isEmptyKey && this.key !== '') {
            this.form = this.customizationService.getDefaultFromGroup(this.key, this.value, this.required, this.readonly, this.disabled);
        }

        // If isActive changes don't update.
        // if (changes && changes.isActive && !changes.isActive.firstChange) {
        //     return;
        // }

        if (changes && changes.showQSButtons && changes.showQSButtons.currentValue) {
            this.showQSButtons = changes.showQSButtons.currentValue;
        }

        // this.fieldValue = this.value;
        // this.fieldFormattedValue = this.formattedValue;

        this.isCaution = this.textColor === '#FF0000';

        // For having the on hide animation.
        // if (this.additionalValue && this.additionalValue.length > 0) {
        //     this.fieldAdditionalValue = this.additionalValue;
        // }

        this.messages = this.notificationInfo && this.notificationInfo.length > 0 ? JSON.parse(this.notificationInfo).Messages : '';
        // this.messages = ["error test"]; // For error check
        if (this.messages && this.messages.length > 0) {
            const fieldControl = this.form.controls[this.key];
            fieldControl.setErrors({
                serverError: 'Error',
            });
            setTimeout(() => {
                if (this.QSInput && this.QSInput.nativeElement) {
                    this.QSInput.nativeElement.focus();
                }
            }, 150);
        } else {
            const self = this;
            setTimeout(() => {
                if (self.lastFocusField) {
                    self.lastFocusField.focus();
                    self.lastFocusField = null;
                } else {
                    self.focusToTheSameElementInTheWantedRow();
                }
            }, 100);
        }
    }

    ngOnDestroy() {
        if (this.resize) {
            this.resize.unsubscribe();
        }

        if (this.valueChanged) {
            this.valueChanged.unsubscribe();
        }

        if (this.elementClicked) {
            this.elementClicked.unsubscribe();
        }
    }

    get getAdditionalValue() {
        return this.additionalValue.length > 0 ? 'show' : 'hide';
    }

    getSameElementInTheWantedRowByClassName(event: any, isNext = true) {
        // TODO:
        return null;

        // const eventTarget = event.target || event.srcElement;
        // let sameElementInTheWantedRowByClassName;

        // let parentSelector;
        // if (this.layoutType === LAYOUT_TYPE.PepperiTable) {
        //     parentSelector = sameElementInTheWantedRowByClassName = $(eventTarget).parents('.table-row');
        // } else if (this.layoutType === LAYOUT_TYPE.PepperiCard) {
        //     parentSelector = sameElementInTheWantedRowByClassName = $(eventTarget).parents('.card-view');

        //     if (parentSelector.length === 0) {
        //         parentSelector = sameElementInTheWantedRowByClassName = $(eventTarget).parents('.line-view');
        //     }
        // }

        // if (isNext) {
        //     if (parentSelector.is(':last-child')) {
        //         sameElementInTheWantedRowByClassName = parentSelector
        //             .parent()
        //             .children()
        //             .first()
        //             .find('[name=' + this.key + ']');
        //     } else {
        //         sameElementInTheWantedRowByClassName = parentSelector.next().find('[name=' + this.key + ']');
        //     }
        // } else {
        //     if (parentSelector.is(':first-child')) {
        //         sameElementInTheWantedRowByClassName = parentSelector
        //             .parent()
        //             .children()
        //             .last()
        //             .find('[name=' + this.key + ']');
        //     } else {
        //         sameElementInTheWantedRowByClassName = parentSelector.prev().find('[name=' + this.key + ']');
        //     }
        // }

        // return sameElementInTheWantedRowByClassName;
    }

    setSameElementInTheWantedRow(event: any, isNext = true) {
        // Navigate to the QS in the next row.
        const target = event.target || event.srcElement;
        this.sameElementInTheWantedRow = this.getSameElementInTheWantedRowByClassName(event, isNext);
        this.QSInput.nativeElement.blur();
    }

    focusToTheSameElementInTheWantedRow() {
        if (this.sameElementInTheWantedRow) {
            // If this is regular item (qs and not button) .
            if (this.sameElementInTheWantedRow.is('input')) {
                this.sameElementInTheWantedRow.click().select();
            } else {
                this.sameElementInTheWantedRow.parent().click();
                this.sameElementInTheWantedRow.focus();
            }
            this.sameElementInTheWantedRow = null;
        }
    }

    cleanError() {
        const fieldControl = this.form.controls[this.key];

        // Clean the error message
        if (this.messages && this.messages.length > 0) {
            this.messages = this.notificationInfo = null;
            fieldControl.setErrors(null);
        }
    }

    onMatrixMouseEnter(event: any) {
        this.isMatrixFocus = true;
    }

    onMatrixMouseleave(event: any) {
        this.isMatrixFocus = false;
    }

    onMatrixClick(event: any) {
        this.isFocus = true;

        if (this.QSInput && this.QSInput.nativeElement) {
            this.QSInput.nativeElement.focus();
        }
    }

    onMatrixBlur(event: any) {
        if (!event.relatedTarget || event.relatedTarget.className.indexOf('qs') < 0) {
            this.isMatrixFocus = false;
        }

        this.onBlur(event);
    }

    onFocus(event: any) {
        this.isFocus = true;
    }

    onBlur(event: any) {
        this.isFocus = false;
        this.cleanError();

        const value = event.target ? event.target.value : event;

        if (parseFloat(this.value) !== parseFloat(value)) {
            this.value = value;
            this.formattedValue = value;
            this.customizationService.updateFormFieldValue(this.form, this.key, value);

            // this.propagateChange(this.value, event.relatedTarget);
            this.changeValue(this.value, event.relatedTarget);
        } else {
            this.focusToTheSameElementInTheWantedRow();
        }
    }

    changeValue(value: any, lastFocusedField: any = null) {
        this.valueChanged.emit({ apiName: this.key, value: value, controlType: this.controlType, lastFocusedField: lastFocusedField });
    }

    increment(event) {
        if (this.standAlone) {
            let tmp = parseFloat(this.value);

            this.value = this.formattedValue = (++tmp).toString();
            this.customizationService.updateFormFieldValue(this.form, this.key, this.value);
        }

        // this.propagateChange('+');
        this.changeValue('+', null);
        event.stopPropagation();
    }

    decrement(event) {
        if (this.standAlone) {
            let tmp = parseFloat(this.value);

            this.value = this.formattedValue = (--tmp).toString();
            this.customizationService.updateFormFieldValue(this.form, this.key, this.value);
        }

        // this.propagateChange('-');
        this.changeValue('-', null);
        event.stopPropagation();
    }

    enterChildren(event) {
        this.elementClicked.emit({ apiName: PepperiQuantitySelectorComponent.ENTER_CHILDREN, eventWhich: event.which });
    }

    enterPackage(event) {
        this.elementClicked.emit({ apiName: PepperiQuantitySelectorComponent.ENTER_PACKAGE, eventWhich: event.which, otherData: this.notificationInfo });
    }

    setQsView() {
        if (!this.showQSButtons) {
            this.showQsBtn = false;
        } else {
            if (this.QSCont && this.QSCont.nativeElement) {
                this.showQsBtn = this.QSCont.nativeElement.clientWidth > 140;
            }
        }

        // Get state class from theme.
        // this.styleClass = this.customizationService.getThemeVariable(CustomizationService.STYLE_QS_KEY);
        this.styleClass = document.documentElement.style.getPropertyValue(CustomizationService.STYLE_QS_KEY) as STYLE_TYPE;

        if (!this.cd['destroyed']) {
            this.cd.detectChanges();
        }
    }

    onKeyPress(event) {
        let inputChar = String.fromCharCode(event.charCode);
        const keyboardEvent = <KeyboardEvent>event;

        if (keyboardEvent.keyCode === 13) {
            this.setSameElementInTheWantedRow(keyboardEvent, !keyboardEvent.shiftKey);
            return true;
        }

        // TODO: Make it one function like in PepperiTextboxComponent
        if (
            /*[8, 9, 27, 13, 190].indexOf(keyboardEvent.keyCode) !== -1 ||*/
            // Allow: Ctrl+A
            (keyboardEvent.keyCode === 65 && keyboardEvent.ctrlKey === true) ||
            // Allow: Ctrl+C
            (keyboardEvent.keyCode === 67 && keyboardEvent.ctrlKey === true) ||
            // Allow: Ctrl+V
            (keyboardEvent.keyCode === 86 && keyboardEvent.ctrlKey === true) ||
            // Allow: Ctrl+X
            (keyboardEvent.keyCode === 88 &&
                keyboardEvent.ctrlKey === true) /*||
            // Allow: home, end, left, right
            (keyboardEvent.keyCode >= 35 && keyboardEvent.keyCode <= 39)*/
        ) {
            // let it happen, don't do anything
            return true;
        }

        if (this.alowDecimal) {
            const decPoint = '.';
            const thousandSeparator = ',';
            const pattern = /^\d[\d,]*(\.\d+)?$/;
            if (keyboardEvent.keyCode === 46) {
                inputChar = inputChar + '0';
            } else if (keyboardEvent.keyCode === 44) {
                inputChar = inputChar + '000';
            }
            if (!pattern.test(event.target.value + inputChar)) {
                keyboardEvent.preventDefault();
            }
        } else {
            const pattern = /[0-9\+\-\ ]/;
            if (!pattern.test(inputChar)) {
                keyboardEvent.preventDefault();
            }
        }
    }
}
