import { Component, ElementRef, Input, Renderer2, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors } from '@angular/forms';

abstract class Evt extends EventTarget {
    abstract get value(): string;
}

@Component({
    selector: 'knk-price',
    templateUrl: './price.component.html',
    styleUrls: ['./price.component.scss'],
    providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: PriceComponent, // forwardRef(() => PriceComponent),
          multi: true
        },
        {
          provide: NG_VALIDATORS,
          useExisting: PriceComponent, // forwardRef(() => PriceComponent),
          multi: true
        }
      ]
})

export class PriceComponent implements ControlValueAccessor {
    priceFirst: string;
    priceSecond: string;
    onChange: (param: string) => void;
    onTouched: () => void;

    @Input('currency') currency: string;
    @Input('precision') precision: number;
    price: number; // @Input('price') price: number;

    @ViewChild('priceFirst') priceFirstCtrl: ElementRef;
    @ViewChild('priceSecond') priceSecondCtrl: ElementRef;

    constructor(private renderer: Renderer2) {
    }

    get priceFirstVal(): string {
        if (this.price) {
            return this.price ? this.price.toString().substr(0, 1) : '0';
        } else {
            return '0';
        }
    }

    get priceSecondVal(): string {
        if (this.price) {
            let s: string = this.price.toString();
            if (s.indexOf('.') !== -1) {
                s = s.substr(s.indexOf('.') + 1, s.length - s.indexOf('.'));
            } else {
                s = '0';
            }
            return this.pad(s, this.precision);
        } else {
            return this.pad('0', this.precision);
        }
    }

    writeValue(value: string): void {
        if (value !== undefined && value !== null) {
            this.price = Number(value);
        }
        this.priceFirst = this.priceFirstVal;
        this.priceSecond = this.priceSecondVal;
        this.renderer.setProperty(this.priceFirstCtrl.nativeElement, 'value', this.priceFirstVal);
        this.renderer.setProperty(this.priceSecondCtrl.nativeElement, 'value', this.priceSecondVal);
    }

    registerOnChange( fn: () => void ): void {
        this.onChange = fn;
    }

    registerOnTouched( fn: () => void ): void {
        this.onTouched = fn;
    }

    changeStart( $event: Event): void {
        let te: Evt = $event.target as Evt;
        this.updateValue(te.value, true);
        if (this.onChange) {
            this.onChange(this.price.toString()); // $event.target.textContent);
        }
        if (this.onTouched) {
            this.onTouched(); // $event.target.textContent);
        }
        $event.stopPropagation();
    }

    changeEnd( $event: Event): void {
        let te: Evt = $event.target as Evt;
        this.updateValue(te.value, false);
        if (this.onChange) {
            this.onChange(this.price.toString()); // $event.target.textContent);
        }
        if (this.onTouched) {
            this.onTouched(); // $event.target.textContent);
        }
        $event.stopPropagation();
    }

    validate(c: FormControl): ValidationErrors {
        if (isNaN(this.price)) {
            return {
                priceError: {
                    valid: false
                }
            };
        }
        return null;
        // return (!this.parseError) ? null : {
        //     jsonParseError: {
        //         valid: false,
        //     },
        // };
    }

    private pad(num: string, size: number): string {
        let s: string = num;
        while (s.length < size) {
            s = s + '0';
        }
        return s;
    }

    private updateValue(val: string, isStart: boolean): void {
        let res: number;
        if (isStart) {
            this.priceFirst = val;
        } else {
            this.priceSecond = val;
        }
        this.price = Number(this.priceFirst + '.' + this.priceSecond);
    }
}
