import * as i0 from '@angular/core';
import { Directive, Input, EventEmitter, ViewChild, Output } from '@angular/core';
import { FormControl } from '@angular/forms';
import { getUniqueNumber, isString, isNullOrUndefined } from '@ironsource/fusion-ui/utils';
import { Subject, BehaviorSubject, Observable, combineLatest, fromEvent, of } from 'rxjs';
import { map, takeUntil, startWith, tap, filter } from 'rxjs/operators';
import { StyleVersion } from '@ironsource/fusion-ui/components/fusion-base';

/*
 * Created on 2020.3.24 By Andy Kononenko (andyk@ironsrc.com)
 */
var InputSize;
(function (InputSize) {
    InputSize["Small"] = "small";
    InputSize["Medium"] = "medium";
})(InputSize || (InputSize = {}));
const DEFAULT_INPUT_OPTIONS = {
    width: '',
    rounded: false,
    isPassHidden: true
};

class InputParameters {
    constructor() {
        /** @internal */
        this._configuration = {};
    }
    /** @internal */
    set configuration(value) {
        this.onConfigurationChanged(value);
    }
    /** @internal */
    set placeholder(placeholder) {
        this.configuration = { ...this._configuration, placeholder };
    }
    /** @internal */
    set errorType(errorType) {
        this.configuration = { ...this._configuration, errorType };
    }
    /** @internal */
    set name(name) {
        this.configuration = { ...this._configuration, name };
    }
    /** @internal */
    set icon(icon) {
        this.configuration = { ...this._configuration, icon };
    }
    /** @internal */
    set units(units) {
        this.configuration = { ...this._configuration, units };
    }
    /** @internal */
    set unitPos(unitPos) {
        this.configuration = { ...this._configuration, unitPos };
    }
    /** @internal */
    set unitPlaceholder(unitPlaceholder) {
        this.configuration = { ...this._configuration, unitPlaceholder };
    }
    /** @internal */
    set btn(btn) {
        this.configuration = { ...this._configuration, btn };
    }
    /** @internal */
    set btnDisabled(btnDisabled) {
        this.configuration = { ...this._configuration, btnDisabled };
    }
    /** @internal */
    set btnLoading(btnLoading) {
        this.configuration = { ...this._configuration, btnLoading };
    }
    /** @internal */
    set id(id) {
        this.configuration = { ...this._configuration, id };
    }
    /** @internal */
    set type(type) {
        this.configuration = { ...this._configuration, type };
    }
    /** @internal */
    set class(value) {
        this.configuration = { ...this._configuration, class: value };
    }
    /** @internal */
    set decimal(decimal) {
        this.configuration = { ...this._configuration, decimal };
    }
    /** @internal */
    set clear(clear) {
        this.configuration = { ...this._configuration, clear };
    }
    /** @internal */
    set readonly(readonly) {
        this.configuration = { ...this._configuration, readonly };
    }
    /** @internal */
    set required(required) {
        this.configuration = { ...this._configuration, required };
    }
    /** @internal */
    set showSearchIcon(showSearchIcon) {
        this.configuration = { ...this._configuration, showSearchIcon };
        if (showSearchIcon !== 'none') {
            this.configuration = { ...this._configuration, ...{ iconPos: showSearchIcon } };
        }
    }
    /** @internal */
    set showSearchIconWhenHasInputValue(showSearchIconWhenHasInputValue) {
        this.configuration = { ...this._configuration, showSearchIconWhenHasInputValue };
    }
    /** @internal */
    set min(min) {
        this.configuration = { ...this._configuration, min };
    }
    /** @internal */
    set max(max) {
        this.configuration = { ...this._configuration, max };
    }
    /** @internal */
    set maxlength(maxlength) {
        this.configuration = { ...this._configuration, maxlength };
    }
    /** @internal */
    set sanitationRegex(sanitationRegex) {
        this.configuration = { ...this._configuration, sanitationRegex };
    }
    /** @internal */
    set acceptFileExtensions(acceptFileExtensions) {
        this.configuration = { ...this._configuration, acceptFileExtensions };
    }
    /** @internal */
    set disableWheelScroll(disableWheelScroll) {
        this.configuration = { ...this._configuration, disableWheelScroll };
    }
    /** @internal */
    set options(options) {
        this.configuration = {
            ...this._configuration,
            options: {
                ...DEFAULT_INPUT_OPTIONS,
                ...(options || {})
            }
        };
    }
    /** @internal */
    // eslint-disable-next-line @angular-eslint/no-input-rename
    set disabled(disabled) {
        this.configuration = { ...this._configuration, disabled };
    }
    /** @internal */
    set error(error) {
        this.configuration = { ...this._configuration, error };
    }
    /** @internal */
    set helperText(helperText) {
        this.configuration = { ...this._configuration, helperText };
    }
    static { this.ɵfac = function InputParameters_Factory(t) { return new (t || InputParameters)(); }; }
    static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: InputParameters, inputs: { configuration: "configuration", placeholder: "placeholder", errorType: "errorType", name: "name", icon: "icon", units: "units", unitPos: "unitPos", unitPlaceholder: "unitPlaceholder", btn: "btn", btnDisabled: "btnDisabled", btnLoading: "btnLoading", id: "id", type: "type", class: "class", decimal: "decimal", clear: "clear", readonly: "readonly", required: "required", showSearchIcon: "showSearchIcon", showSearchIconWhenHasInputValue: "showSearchIconWhenHasInputValue", min: "min", max: "max", maxlength: "maxlength", sanitationRegex: "sanitationRegex", acceptFileExtensions: "acceptFileExtensions", disableWheelScroll: "disableWheelScroll", options: "options", disabled: [i0.ɵɵInputFlags.None, "isDisabled", "disabled"], error: "error", helperText: "helperText" } }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(InputParameters, [{
        type: Directive
    }], null, { configuration: [{
            type: Input
        }], placeholder: [{
            type: Input
        }], errorType: [{
            type: Input
        }], name: [{
            type: Input
        }], icon: [{
            type: Input
        }], units: [{
            type: Input
        }], unitPos: [{
            type: Input
        }], unitPlaceholder: [{
            type: Input
        }], btn: [{
            type: Input
        }], btnDisabled: [{
            type: Input
        }], btnLoading: [{
            type: Input
        }], id: [{
            type: Input
        }], type: [{
            type: Input
        }], class: [{
            type: Input
        }], decimal: [{
            type: Input
        }], clear: [{
            type: Input
        }], readonly: [{
            type: Input
        }], required: [{
            type: Input
        }], showSearchIcon: [{
            type: Input
        }], showSearchIconWhenHasInputValue: [{
            type: Input
        }], min: [{
            type: Input
        }], max: [{
            type: Input
        }], maxlength: [{
            type: Input
        }], sanitationRegex: [{
            type: Input
        }], acceptFileExtensions: [{
            type: Input
        }], disableWheelScroll: [{
            type: Input
        }], options: [{
            type: Input
        }], disabled: [{
            type: Input,
            args: ['isDisabled']
        }], error: [{
            type: Input
        }], helperText: [{
            type: Input
        }] }); })();

const SPECIAL_KEYS = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Backspace', 'Tab', 'End', 'Home', 'Enter', 'Escape'];
const ENTER_KEY_CODE = 'Enter';
const ESCAPE_KEY_CODE = 'Escape';
const INPUT_DEFAULT_CONFIGURATION = {
    placeholder: '',
    disabled: false,
    disableOnLoading: true,
    errorType: '',
    btnDisabled: false,
    btnLoading: false,
    id: getUniqueNumber(),
    type: 'text',
    class: '',
    showSearchIcon: 'none',
    showSearchIconWhenHasInputValue: false,
    acceptFileExtensions: '*/*',
    options: { ...DEFAULT_INPUT_OPTIONS }
};

const _c0 = ["input"];
const _c1 = ["fileInput"];
class InputBaseComponent extends InputParameters {
    constructor(
    /** @internal */
    elementRef) {
        super();
        this.elementRef = elementRef;
        /** @internal */
        // Todo - think about a way to use it with generic way to listen to all kind of events
        /** @internal */
        this.ngFocus = new EventEmitter();
        /** @internal */
        this.ngBlur = new EventEmitter();
        /** @internal */
        this.ngEnter = new EventEmitter();
        /** @internal */
        this.ngEscape = new EventEmitter();
        /** @internal */
        this.btnAction = new EventEmitter();
        /** @internal */
        this.passHiddenStateChanged = new EventEmitter();
        /** @internal */
        this.onDestroy$ = new Subject();
        /** @internal */
        this.inputControl = new FormControl();
        /** @internal */
        this.file = new FormControl();
        /** @internal */
        this.showErrorClass$ = new BehaviorSubject(false);
        /** @internal */
        this.configByStyle$ = new Observable();
        /** @internal */
        this.disabled$ = new BehaviorSubject(false);
        /** @internal */
        this.isDisabledInput$ = new BehaviorSubject(false);
        /** @internal */
        this.isDisabledFormControl$ = new BehaviorSubject(false);
        this._isPassHidden = true;
        /**
         * Method to call when the input value has changes.
         * @internal
         */
        this.propagateChange = (_) => { };
    }
    get config() {
        return { ...INPUT_DEFAULT_CONFIGURATION, ...this._configuration };
    }
    get isSmall() {
        return this.config.options?.size === 'small';
    }
    set isPassHidden(val) {
        this._isPassHidden = val;
    }
    get isPassHidden() {
        return this._isPassHidden;
    }
    get isReadOnly() {
        return (this.config?.readonly || this.disabled$.getValue() || (this.loading && this.config?.disableOnLoading) || this.config?.btnLoading);
    }
    // Todo - use optional chaining when upgrade ts version
    get displaySearchIcon() {
        const inputValue = this.input ? this.input.nativeElement.value : null;
        return (this.config.showSearchIcon !== 'none' && (!inputValue || (this.config.showSearchIconWhenHasInputValue && !this.config.clear)));
    }
    ngOnInit() {
        this.step = this.getStepIndication();
        this.inputControlValueChanges$ = this.inputControl.valueChanges;
        this.fileControlValueChanges$ = this.getFileControlValueChangesObservable();
        this.configByStyle$ = this.getConfigStyleObservable();
        this.showErrorClass$.next(!!this.config.error);
        this.isPassHidden = this.config.options.isPassHidden;
        this.initChangesTrigger();
        this.initDisabledStateChanged();
    }
    ngAfterViewInit() {
        this.setInputElementListeners();
        this.setMouseWheelListener();
        this.setKeyDownListener();
    }
    ngOnDestroy() {
        this.onDestroy$.next();
        this.onDestroy$.complete();
    }
    /** @internal */
    initChangesTrigger() {
        const valueChanges$ = this.config.type === 'file'
            ? this.fileControlValueChanges$.pipe(map(_ => this.fileInput.nativeElement.files))
            : this.inputControlValueChanges$;
        valueChanges$.pipe(takeUntil(this.onDestroy$)).subscribe(value => {
            this.propagateChange(value);
        });
    }
    initDisabledStateChanged() {
        combineLatest([this.isDisabledFormControl$.asObservable(), this.isDisabledInput$.asObservable()])
            .pipe(startWith([false, false]), takeUntil(this.onDestroy$))
            .subscribe(([isDisabledInput, isDisabledFormControl]) => {
            this.disabled$.next(isDisabledInput || isDisabledFormControl);
        });
    }
    /** @internal */
    onConfigurationChanged(value) {
        this.onOptionsChanged({ previousValue: this.config.options, currentValue: value.options });
        this.onDisabledChanged({ previousValue: this.config.disabled, currentValue: value.disabled });
        this.onErrorChanged({ previousValue: this.config.error, currentValue: value.error });
        this._configuration = value;
    }
    /** @internal */
    getHolderClasses() {
        return [
            this.config.errorType === 'error' && 'fu-error-error',
            this.config.errorType === 'warning' && 'fu-error-warning',
            this.config.showSearchIcon !== 'none' && 'fu-has-search-icon',
            this.config.showSearchIcon === 'right' && 'fu-search-icon-right-position',
            !!this.config.btn && 'fu-button',
            !!this.focused && 'focused',
            (this.disabled$.getValue() || this.loading || this.config.btnLoading) && 'fu-disabled',
            !!this.config.options.rounded && 'fu-rounded'
        ].filter(Boolean);
    }
    /** @internal */
    showErrorIcon() {
        return true;
    }
    /** @internal */
    getErrorIcon(errorType, infoIconName, warningIconName) {
        return errorType === 'error' ? infoIconName : errorType === 'warning' ? warningIconName : '';
    }
    /** @internal */
    getTooltipErrorsMessage() {
        return isString(this.config.error) ? this.config.error : '';
    }
    /** @internal */
    blur() {
        this.focused = false;
        this.input.nativeElement.blur();
        if (this.ngBlur) {
            this.ngBlur.emit();
        }
        if (this.onBlur) {
            this.onBlur(this.inputControl.value);
        }
    }
    /** @internal */
    focus() {
        this.focused = true;
        if (this.ngFocus) {
            this.ngFocus.emit();
        }
    }
    /** @internal */
    onButtonClicked($event) {
        if (this.config.type === 'file') {
            this.fileInput.nativeElement.click();
        }
        else if (this.btnAction) {
            this.btnAction.emit($event);
        }
    }
    /** @internal */
    clearInput(isFocused = false) {
        this.inputControl.setValue('');
        if (isFocused) {
            this.setFocus();
        }
    }
    /** @internal */
    setFocus() {
        this.input.nativeElement.focus();
    }
    /** @internal */
    passToggle($event) {
        const passShownState = this.config.options.hasOwnProperty('isPassHidden') ? this.isPassHidden : true;
        if (!isNullOrUndefined($event)) {
            this.isPassHidden = !this.isPassHidden;
            this.setFocus();
            this.passHiddenStateChanged.emit(!passShownState);
        }
    }
    /** @internal */
    getInputType() {
        return this.config.type === 'file' || (this.config.type === 'password' && !this.isPassHidden) ? 'text' : this.config.type;
    }
    /** @internal */
    onPassToggleMouseDown($event) {
        $event.preventDefault();
    }
    /** @internal */
    toggleErrorClass(error) {
        this.showErrorClass$.next(error);
    }
    /** @internal */
    writeValue(value) {
        if (isNullOrUndefined(value)) {
            this.clearInput();
        }
        else {
            if (this.config.type === 'number' && Number.isInteger(this.config.decimal) && this.config.decimal > 0) {
                value = parseFloat(value).toFixed(this.config.decimal);
            }
            this.inputControl.setValue(value, { emitEvent: false });
        }
    }
    /** @internal */
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    /** @internal */
    registerOnTouched(fn) {
        this.onBlur = fn;
    }
    /** @internal */
    setDisabledState(isDisabled) {
        this.isDisabledFormControl$.next(isDisabled);
    }
    getStepIndication() {
        if (Number.isInteger(this.config.decimal) && this.config.decimal > 0) {
            return '0.' + new Array(this.config.decimal).fill('0').slice(0, -1).join('') + '1';
        }
    }
    setPasswordShownState(value) {
        if (!!value && !isNullOrUndefined(value.isPassHidden)) {
            this.passToggle(null);
        }
    }
    // Todo - use optional chaining when upgrade ts version
    getFileControlValueChangesObservable() {
        return this.file.valueChanges.pipe(tap(value => {
            const fileName = this.fileInput.nativeElement.files && this.fileInput.nativeElement.files[0]
                ? this.fileInput.nativeElement.files[0].name
                : value;
            this.inputControl.setValue(fileName, { emitEvent: false });
            this.inputControl.disable({ emitEvent: false });
        }));
    }
    // Todo - use optional chaining when upgrade ts version
    setInputElementListeners() {
        const hasPreventCharacters = this.config.options && this.config.options.preventCharacters && this.config.options.preventCharacters.length;
        const hasEscapeEmitterListeners = this.ngEscape.observers.length;
        const hasEnterEmitterListeners = this.ngEnter.observers.length;
        if (!isNullOrUndefined(this.input) && (hasPreventCharacters || hasEscapeEmitterListeners || hasEnterEmitterListeners)) {
            fromEvent(this.input.nativeElement, 'keydown')
                .pipe(filter((event) => {
                return ((hasEscapeEmitterListeners && event.key === ESCAPE_KEY_CODE) ||
                    (hasEnterEmitterListeners && event.key === ENTER_KEY_CODE) ||
                    (hasPreventCharacters && this.config.options.preventCharacters.includes(event.key)));
            }), takeUntil(this.onDestroy$))
                .subscribe(this.inputKeydownHandler.bind(this));
        }
    }
    inputKeydownHandler(event) {
        if (event.key === ENTER_KEY_CODE) {
            this.ngEnter.emit(this.inputControl.value);
        }
        else if (event.key === ESCAPE_KEY_CODE) {
            this.ngEscape.emit(this.inputControl.value);
        }
        else {
            event.preventDefault();
            return false;
        }
    }
    setMouseWheelListener() {
        if (this.config.disableWheelScroll && this.config.type === 'number') {
            fromEvent(this.elementRef.nativeElement, 'mousewheel')
                .pipe(takeUntil(this.onDestroy$))
                .subscribe(($event) => $event.preventDefault());
        }
    }
    setKeyDownListener() {
        if (this.config.sanitationRegex) {
            const regex = new RegExp(this.config.sanitationRegex);
            fromEvent(this.elementRef.nativeElement, 'keydown')
                .pipe(filter(($event) => !(SPECIAL_KEYS.indexOf($event.key) !== -1) && !regex.test($event.key)), takeUntil(this.onDestroy$))
                .subscribe(($event) => $event.preventDefault());
        }
    }
    onOptionsChanged({ previousValue, currentValue }) {
        if (currentValue !== previousValue) {
            this.setPasswordShownState(currentValue);
        }
    }
    onDisabledChanged({ previousValue, currentValue }) {
        if (currentValue !== previousValue) {
            this.isDisabledInput$.next(currentValue);
        }
    }
    onErrorChanged({ previousValue, currentValue }) {
        if (currentValue !== previousValue) {
            this.toggleErrorClass(!!currentValue);
        }
    }
    getConfigStyleObservable() {
        return of({});
    }
    static { this.ɵfac = function InputBaseComponent_Factory(t) { return new (t || InputBaseComponent)(i0.ɵɵdirectiveInject(i0.ElementRef)); }; }
    static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: InputBaseComponent, viewQuery: function InputBaseComponent_Query(rf, ctx) { if (rf & 1) {
            i0.ɵɵviewQuery(_c0, 5);
            i0.ɵɵviewQuery(_c1, 5);
        } if (rf & 2) {
            let _t;
            i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.input = _t.first);
            i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.fileInput = _t.first);
        } }, inputs: { loading: "loading" }, outputs: { ngFocus: "ngFocus", ngBlur: "ngBlur", ngEnter: "ngEnter", ngEscape: "ngEscape", btnAction: "btnAction", passHiddenStateChanged: "passHiddenStateChanged" }, features: [i0.ɵɵInheritDefinitionFeature] }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(InputBaseComponent, [{
        type: Directive
    }], () => [{ type: i0.ElementRef }], { input: [{
            type: ViewChild,
            args: ['input', { static: false }]
        }], fileInput: [{
            type: ViewChild,
            args: ['fileInput', { static: false }]
        }], loading: [{
            type: Input
        }], ngFocus: [{
            type: Output
        }], ngBlur: [{
            type: Output
        }], ngEnter: [{
            type: Output
        }], ngEscape: [{
            type: Output
        }], btnAction: [{
            type: Output
        }], passHiddenStateChanged: [{
            type: Output
        }] }); })();

/*
 * Created on 2020.4.21 By Andy Kononenko (andyk@ironsrc.com)
 */
const CONFIG_INPUT_BY_UI_STYLE = {
    style_v1: {
        iconSearch: { iconName: 'search', iconVersion: 'v1' },
        iconClear: { iconName: 'clear-full-circle', iconVersion: 'v1' },
        iconInfo: { iconName: 'info', iconVersion: 'v1' },
        iconWarning: { iconName: 'warning', iconVersion: 'v1' },
        iconLoader: { iconName: 'loading', iconVersion: 'v1' },
        currentStyleVersion: StyleVersion.V1
    },
    style_v2: {
        iconSearch: { iconName: 'search', iconVersion: 'v2' },
        iconClear: { iconName: 'close-circle', iconVersion: 'v2' },
        iconInfo: { iconName: 'importent', iconVersion: 'v2' },
        iconWarning: { iconName: 'warning', iconVersion: 'v2' },
        iconLoader: { iconName: 'loading-rotate', iconVersion: 'v2' },
        currentStyleVersion: StyleVersion.V2
    },
    style_v3: {
        iconInfo: 'importent',
        iconWarning: 'warning',
        currentStyleVersion: StyleVersion.V3
    }
};

/**
 * Generated bundle index. Do not edit.
 */

export { CONFIG_INPUT_BY_UI_STYLE, DEFAULT_INPUT_OPTIONS, ENTER_KEY_CODE, ESCAPE_KEY_CODE, INPUT_DEFAULT_CONFIGURATION, InputBaseComponent, InputSize, SPECIAL_KEYS };
//# sourceMappingURL=ironsource-fusion-ui-components-input-common-base.mjs.map
