import Input from "../Input";
import InputFactory, {InputImplConfig} from "../InputFactory";

export default class StringInput extends Input<string>{
    public placeholder: string|null = null;

    constructor(params: Partial<StringInput>) {
        super(params);
        Object.assign(this, params);
    }

    public placeHtml(container: HTMLElement): void {
        const questionContainer = this.getQuestionContainer();
        questionContainer.classList.add("pad-text-input");
        container.append(questionContainer);
        this.placedHtml.push(questionContainer);
    }

    protected getInputElement(): HTMLElement {
        const inputElement = document.createElement("input");
        inputElement.type = "text";
        inputElement.name = this.getFullPathName();
        inputElement.setAttribute("autocomplete", this.autocomplete);
        if(this.placeholder) inputElement.placeholder = this.placeholder;

        inputElement.addEventListener("input", () => {
            let value: string|null = inputElement.value;
            if (value === "") value = null;
            this.value = value;
        });

        inputElement.addEventListener("change", () => {
            this.saveValue();
        });

        this.onChange.add(event => {
            inputElement.value = event.value ?? "";
        });

        this.getDataNode().onChange.add(event => {
            inputElement.value = event.value ?? "";
        });

        this.getDataNode().onReset.add( () => {
            this.value = undefined;
            inputElement.value = this.getDataNode().valueOrDefault ?? "";
        });

        inputElement.value = this._value ?? this.getDataNode().valueOrDefault ?? "";
        return inputElement;
    }
}

export function addStringInputToFactory(factory: InputFactory): void {
    factory.registerConstructor("string", (config, params) => {
        const impl = config.impl;
        if (!isStringInputConfig(impl)) return null;

        const stringInputParam: Partial<StringInput> = params as Partial<StringInput>;

        stringInputParam.placeholder = impl.placeholder;

        return new StringInput(stringInputParam);
    });
}

function isStringInputConfig(config: InputImplConfig): config is StringInputConfig{
    return config.type === "string";
}

interface StringInputConfig extends InputImplConfig{
    type: "string";
    placeholder: string|null;
}