"use strict";
/*
 * Copyright (c) 2021-2022.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseQuerySort = void 0;
const utils_1 = require("../../utils");
const fields_1 = require("../fields");
const utils_2 = require("../utils");
const utils_3 = require("./utils");
// --------------------------------------------------
function isMultiDimensionalArray(arr) {
    if (!Array.isArray(arr)) {
        return false;
    }
    return arr.length > 0 && Array.isArray(arr[0]);
}
function buildDefaultSortParseOutput(options) {
    if (options.default) {
        const output = [];
        const flatten = (0, utils_1.flattenNestedObject)(options.default);
        const keys = Object.keys(flatten);
        for (let i = 0; i < keys.length; i++) {
            const fieldDetails = (0, utils_1.getFieldDetails)(keys[i]);
            let path;
            if (fieldDetails.path) {
                path = fieldDetails.path;
            }
            else if (options.defaultPath) {
                path = options.defaultPath;
            }
            output.push(Object.assign(Object.assign({ key: fieldDetails.name }, (path ? { path } : {})), { value: flatten[keys[i]] }));
        }
        return output;
    }
    return [];
}
/**
 * Transform sort data to appreciate data format.
 * @param data
 * @param options
 */
function parseQuerySort(data, options) {
    options = options !== null && options !== void 0 ? options : {};
    // If it is an empty array nothing is allowed
    if (typeof options.allowed !== 'undefined') {
        const allowed = (0, utils_2.flattenParseAllowedOption)(options.allowed);
        if (allowed.length === 0) {
            return buildDefaultSortParseOutput(options);
        }
    }
    options.mapping = options.mapping || {};
    const prototype = Object.prototype.toString.call(data);
    /* istanbul ignore next */
    if (prototype !== '[object String]' &&
        prototype !== '[object Array]' &&
        prototype !== '[object Object]') {
        return buildDefaultSortParseOutput(options);
    }
    if (typeof options.allowed === 'undefined' &&
        options.default) {
        const flatten = (0, utils_1.flattenNestedObject)(options.default);
        options.allowed = Object.keys(flatten);
    }
    let parts = [];
    if (typeof data === 'string') {
        parts = data.split(',');
    }
    if (Array.isArray(data)) {
        parts = data.filter((item) => typeof item === 'string');
    }
    if (typeof data === 'object' &&
        data !== null) {
        const keys = Object.keys(data);
        for (let i = 0; i < keys.length; i++) {
            /* istanbul ignore next */
            if (!(0, utils_1.hasOwnProperty)(data, keys[i]) ||
                typeof keys[i] !== 'string' ||
                typeof data[keys[i]] !== 'string')
                continue;
            const fieldPrefix = data[keys[i]]
                .toLowerCase() === 'desc' ? '-' : '';
            parts.push(fieldPrefix + keys[i]);
        }
    }
    const items = {};
    let matched = false;
    for (let i = 0; i < parts.length; i++) {
        const { value, direction } = (0, utils_3.parseSortValue)(parts[i]);
        parts[i] = value;
        const key = (0, utils_1.applyMapping)(parts[i], options.mapping);
        const fieldDetails = (0, utils_1.getFieldDetails)(key);
        if (typeof options.allowed === 'undefined' &&
            !(0, fields_1.isValidFieldName)(fieldDetails.name)) {
            continue;
        }
        if (!(0, utils_1.isFieldPathAllowedByRelations)(fieldDetails, options.relations) &&
            !(0, utils_1.isFieldNonRelational)(fieldDetails)) {
            continue;
        }
        const keyWithAlias = (0, utils_1.buildFieldWithPath)(fieldDetails);
        if (typeof options.allowed !== 'undefined' &&
            !isMultiDimensionalArray(options.allowed) &&
            !(0, utils_2.isPathCoveredByParseAllowedOption)(options.allowed, [key, keyWithAlias])) {
            continue;
        }
        matched = true;
        let path;
        if (fieldDetails.path) {
            path = fieldDetails.path;
        }
        else if (options.defaultPath) {
            path = options.defaultPath;
        }
        items[keyWithAlias] = Object.assign(Object.assign({ key: fieldDetails.name }, (path ? { path } : {})), { value: direction });
    }
    if (!matched) {
        return buildDefaultSortParseOutput(options);
    }
    if (isMultiDimensionalArray(options.allowed)) {
        // eslint-disable-next-line no-labels,no-restricted-syntax
        outerLoop: for (let i = 0; i < options.allowed.length; i++) {
            const temp = [];
            const keyPaths = (0, utils_2.flattenParseAllowedOption)(options.allowed[i]);
            for (let j = 0; j < keyPaths.length; j++) {
                let keyWithAlias = keyPaths[j];
                let key;
                const parts = keyWithAlias.split('.');
                if (parts.length > 1) {
                    key = parts.pop();
                }
                else {
                    key = keyWithAlias;
                    keyWithAlias = (0, utils_1.buildKeyPath)(key, options.defaultPath);
                }
                if ((0, utils_1.hasOwnProperty)(items, key) ||
                    (0, utils_1.hasOwnProperty)(items, keyWithAlias)) {
                    const item = (0, utils_1.hasOwnProperty)(items, key) ?
                        items[key] :
                        items[keyWithAlias];
                    temp.push(item);
                }
                else {
                    // eslint-disable-next-line no-labels
                    continue outerLoop;
                }
            }
            return temp;
        }
        // if we get no match, the sort data is invalid.
        return [];
    }
    return Object.values(items);
}
exports.parseQuerySort = parseQuerySort;
//# sourceMappingURL=parse.js.map