"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.valueAsNumber = exports.valueAsString = exports.valueAsBoolean = void 0;
const optional_1 = require("../../types/optional");
const validation = require("../validation");
/**
 * Attempt to coerce the given value to a boolean.
 *
 * @see asBoolean
 * @param value - the value to coerce
 * @param policy - determines when validation errors are added to the current validation context
 * @param path - an optional string appended to validation errors to identify where this value originated
 * @returns a boolean if the value was a boolean or coercible to a boolean, otherwise null
 */
function valueAsBoolean(value, policy = "coercible", path) {
    if (!(0, optional_1.isSome)(value)) {
        return value;
    }
    if (typeof value === "boolean") {
        return value;
    }
    // Handle string coercion
    if (typeof value === "string") {
        if (value === "true") {
            return true;
        }
        else if (value === "false") {
            return false;
        }
    }
    // Else coerce.
    const coercedValue = Boolean(value);
    switch (policy) {
        case "strict": {
            validation.context("asBoolean", () => {
                validation.unexpectedType("coercedValue", "boolean", value, path);
            });
            break;
        }
        case "coercible": {
            if ((0, optional_1.isNothing)(coercedValue)) {
                validation.context("asBoolean", () => {
                    validation.unexpectedType("coercedValue", "boolean", value, path);
                });
                return null;
            }
            break;
        }
        case "none":
        default: {
            break;
        }
    }
    return coercedValue;
}
exports.valueAsBoolean = valueAsBoolean;
/**
 * Attempt to coerce the given value to a string.
 *
 * @see asString
 * @param value - the value to coerce
 * @param policy - determines when validation errors are added to the current validation context
 * @param path - an optional string appended to validation errors to identify where this value originated
 * @returns a string if the value was a string or coercible to a string, otherwise null
 */
function valueAsString(value, policy = "coercible", path) {
    if (!(0, optional_1.isSome)(value)) {
        return value;
    }
    if (typeof value === "string") {
        return value;
    }
    // We don't consider arbitrary objects as convertable to strings even through they will result in some value
    const coercedValue = typeof value === "object" ? null : String(value);
    switch (policy) {
        case "strict": {
            validation.context("asString", () => {
                validation.unexpectedType("coercedValue", "string", value, path);
            });
            break;
        }
        case "coercible": {
            if ((0, optional_1.isNothing)(coercedValue)) {
                validation.context("asString", () => {
                    validation.unexpectedType("coercedValue", "string", value, path);
                });
            }
            break;
        }
        case "none":
        default: {
            break;
        }
    }
    return coercedValue;
}
exports.valueAsString = valueAsString;
/**
 * Attempt to coerce the given value to a number.
 *
 * @see asNumber
 * @param value - the value to coerce
 * @param policy - determines when validation errors are added to the current validation context
 * @param path - an optional string appended to validation errors to identify where this value originated
 * @returns a number if the value was a number or coercible to a number, otherwise null
 */
function valueAsNumber(value, policy = "coercible", path) {
    if (!(0, optional_1.isSome)(value)) {
        return value;
    }
    if (typeof value === "number") {
        return value;
    }
    const coercedValue = Number(value);
    switch (policy) {
        case "strict": {
            validation.context("asNumber", () => {
                validation.unexpectedType("coercedValue", "number", value, path);
            });
            break;
        }
        case "coercible": {
            if (isNaN(coercedValue)) {
                validation.context("asNumber", () => {
                    validation.unexpectedType("coercedValue", "number", value, path);
                });
                return null;
            }
            break;
        }
        case "none":
        default: {
            break;
        }
    }
    return coercedValue;
}
exports.valueAsNumber = valueAsNumber;
//# sourceMappingURL=coercion.js.map