import Validator from "../Validator";
import ValidatorFactory, {ValidatorConfig} from "../ValidatorFactory";

export default class Required extends Validator{
    public zeroIsInvalid: boolean = false;

    public validate(value: any): true|string {
        if (!this._isValid) return true;
        if (value === null || value === undefined) return this.errorMessage;
        if (typeof value === "string" && value.trim() === "") return this.errorMessage;
        if (typeof value === "number" && (isNaN(value) || (this.zeroIsInvalid && value === 0))) return this.errorMessage;
        if (typeof value === "boolean" && !value) return this.errorMessage;
        if (typeof value === "object" && Object.keys(value).length === 0) return this.errorMessage
        if (Array.isArray(value) && value.length === 0) return this.errorMessage;
        return true;
    }

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

interface RequiredConfig extends ValidatorConfig {
    type: "required";
    zeroIsInvalid: boolean;
}

function isRequiredConfig(config: ValidatorConfig): config is RequiredConfig {
    return config.type === "required";
}

export function addRequiredValidatorToFactory(factory: ValidatorFactory): void {
    factory.registerConstructor("required", (config, params) => {
        if (!isRequiredConfig(config)) return null;
        const requiredParam: Partial<Required> = params as Partial<Required>;
        requiredParam.zeroIsInvalid = config.zeroIsInvalid;

        return new Required(requiredParam);
    });
}