import { CleaveOptions } from "cleave.js/options";
import Cleave from "cleave.js/dist/cleave-esm";

export interface INumericInputModuleOptions {
    numeral?: boolean;
    integerCount?: number;
    decimalCount?: number;
    decimalMark?: string;
    thousandSeparatorMark?: string;
    positiveOnly?: boolean;
    prefix?: string;
    blocks?: number[];
    stripLeadingZeroes?: boolean;
}

export default class NumericInputModule {

    public $element: JQuery;
    public cleave: Cleave;

    constructor(selectorOrElement: string | Element, options: INumericInputModuleOptions) {

        const cleaveOptions = this.transformOptionsToCleaveOptions(options);

        this.$element = $(selectorOrElement as any);

        if (this.$element.length === 0) {
            throw Error("NumericInputModule cannot find any element with input \"" + selectorOrElement + "\"");
        }

        if (this.$element.length > 1) {
            throw Error("NumericInputModule found " + this.$element.length + " elements with \"" + selectorOrElement + "\". Only 1 is allowed.");
        }

        if (this.$element.data("numericinput-module-initialized") === true) {
            return;
        }

        if (options.positiveOnly === undefined) {
            options.positiveOnly = false;
        }

        if (options.stripLeadingZeroes === undefined) {
            options.stripLeadingZeroes = true;
        }

        const cleaveDefaultOptions: CleaveOptions = {
            numeral: true,
            numeralIntegerScale: options.integerCount,
            numeralPositiveOnly: options.positiveOnly,
            numeralDecimalScale: 0,
            numeralDecimalMark: ",",
            delimiter: "",
            numericOnly: true,
            rawValueTrimPrefix: true,
            blocks: [],
            stripLeadingZeroes: options.stripLeadingZeroes
        };

        $.extend(true, cleaveDefaultOptions, cleaveOptions);
        this.cleave = new Cleave(this.$element[0], cleaveDefaultOptions);

        this.$element.data("numericinput-module", this);

        this.$element.data("numericinput-module-initialized", true);

        let oldValue = this.cleave.getRawValue();

        const self = this;
        this.$element.on("blur",
            function() {
                const newValue = self.cleave.getRawValue();

                if (oldValue !== newValue) {
                    self.$element.trigger("numeric-change-iefix");
                    oldValue = newValue;
                }
            });
    }

    public transformOptionsToCleaveOptions(options: INumericInputModuleOptions): CleaveOptions {

        const cleaveOptions: CleaveOptions = {
            numeralDecimalScale: options.decimalCount,
            numeralDecimalMark: options.decimalMark,
            delimiter: options.thousandSeparatorMark,
        };

        $.extend(true, cleaveOptions, options);

        return cleaveOptions;
    }

    public getRawValue(): number {

        const rawValue = this.cleave.getRawValue();

        const rawFloatValue = parseFloat(rawValue);

        return rawFloatValue;
    }

    public setRawValue(value: string | number) {

        if (typeof value === "number") {
            value = value.toString();
        }

        this.cleave.setRawValue(value);
    }

    public getFormattedValue(): string {
        
        const formattedValue = this.cleave.getFormattedValue();
    
        return formattedValue;
    }
}
