"use strict";
/*
 * @adonisjs/validator
 *
 * (c) Harminder Virk <virk@adonisjs.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRequestReporter = exports.wrapCompile = exports.ensureValidArgs = exports.resolveAbsoluteName = exports.getFieldValue = exports.isRef = exports.enforceDateTime = exports.enforceArray = exports.isObject = exports.exists = exports.existsStrict = void 0;
const luxon_1 = require("luxon");
const utils_1 = require("@poppinss/utils");
const ErrorReporters = __importStar(require("../ErrorReporter"));
/**
 * Ensure value is not `undefined`
 */
function existsStrict(value) {
    return value !== undefined && value !== null;
}
exports.existsStrict = existsStrict;
/**
 * Ensure that value exists. Empty string, null and undefined
 * fails the exists check.
 */
function exists(value) {
    return !!value || value === false || value === 0;
}
exports.exists = exists;
/**
 * Ensure value is a valid Object. Returns false for `Array` and `null`
 */
function isObject(value) {
    return value !== null && typeof value === 'object' && !Array.isArray(value);
}
exports.isObject = isObject;
/**
 * Enforces the value to be an array
 */
function enforceArray(value, message) {
    if (!Array.isArray(value)) {
        throw new Error(message || 'Expected value to be an array');
    }
}
exports.enforceArray = enforceArray;
/**
 * Enforces the value to be an instance of luxon DateTime object
 */
function enforceDateTime(value, message) {
    if (luxon_1.DateTime.isDateTime(value) === false) {
        throw new Error(message || 'Expected value to be an instance of luxon DateTime object');
    }
}
exports.enforceDateTime = enforceDateTime;
/**
 * Returns a boolean telling value is a schema ref
 */
function isRef(value) {
    return value && value.__$isRef === true;
}
exports.isRef = isRef;
/**
 * Returns the field value for a given pointer. If pointer starts
 * with `/`, then it will be searched from the root of the
 * object, otherwise it's searched from the nearest tip
 */
function getFieldValue(field, root, tip) {
    return field[0] === '/' ? utils_1.lodash.get(root, field.slice(1)) : tip[field];
}
exports.getFieldValue = getFieldValue;
/**
 * Resolves the field name in relation to the other field. If field name
 * starts with `/` it is returned as it is by removing `/`. Otherwise
 * the other field pointer is used to make the absolute name
 */
function resolveAbsoluteName(field, otherField) {
    return field[0] === '/'
        ? field.slice(1)
        : otherField.split('.').slice(0, -1).concat(field).join('.');
}
exports.resolveAbsoluteName = resolveAbsoluteName;
/**
 * Validates to ensure that arguments passed to validations compile method
 * is an array
 */
function ensureValidArgs(ruleName, args) {
    /**
     * The compile method must receive an array of spread arguments. If not
     * it means the user has not used `Rules.<rule>` in order to use the
     * validation rule, since `Rules.<rule>` always passes an array of
     * options.
     */
    if (!Array.isArray(args)) {
        throw new Error(`"${ruleName}": The 3rd argument must be a combined array of arguments`);
    }
}
exports.ensureValidArgs = ensureValidArgs;
/**
 * Wraps the custom compile function to DRY the repetitive code inside every
 * validation rule.
 *
 * - It ensures that options received by the compile methods is a valid array.
 * - Validates for the restricted subtypes (if defined)
 * - Prepares a default set of parsedRules properties.
 * - Invokes the callback (if defined).
 */
function wrapCompile(name, restrictForTypes, customCallback) {
    return function (type, subtype, options, rulesTree) {
        /**
         * Ensure options are defined as an array
         */
        ensureValidArgs(name, options);
        /**
         * Restrict sub-types when defined
         */
        if (restrictForTypes && restrictForTypes.length && !restrictForTypes.includes(subtype)) {
            throw new Error(`"${name}": Rule can only be used with "schema.<${restrictForTypes.join(',')}>" type(s)`);
        }
        /**
         * Default options
         */
        const defaultOptions = {
            name: name,
            allowUndefineds: false,
            async: false,
            compiledOptions: options,
        };
        /**
         * Invoke user defined callback and merge return value with defaults
         */
        if (typeof customCallback === 'function') {
            Object.assign(defaultOptions, customCallback(options, type, subtype, rulesTree));
        }
        return defaultOptions;
    };
}
exports.wrapCompile = wrapCompile;
/**
 * Returns the error reporter for the current HTTP request
 */
function getRequestReporter(request) {
    if (request.ajax()) {
        return ErrorReporters.ApiErrorReporter;
    }
    switch (request.accepts(['html', 'application/vnd.api+json', 'json'])) {
        case 'html':
        case null:
            return ErrorReporters.VanillaErrorReporter;
        case 'json':
            return ErrorReporters.ApiErrorReporter;
        case 'application/vnd.api+json':
            return ErrorReporters.JsonApiErrorReporter;
    }
}
exports.getRequestReporter = getRequestReporter;
