var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import Debug from 'debug';
import gql from 'graphql-tag';
const debug = Debug('deeplinks:gql:query');
const log = debug.extend('log');
const error = debug.extend('error');
const fieldsInputs = (tableName) => ({
    'distinct_on': `[${tableName}_select_column!]`,
    'limit': `Int`,
    'offset': `Int`,
    'order_by': `[${tableName}_order_by!]`,
    'where': `${tableName}_bool_exp!`,
});
const manyRelations = {
    'from': false,
    'to': false,
    'type': false,
    'in': true,
    'out': true,
    'typed': true,
};
export const generateQueryData = ({ tableName, tableNamePostfix = '', operation = 'query', queryName = `${tableName}`, returning = `id`, variables: _variables, }) => {
    log('generateQuery', { tableName, tableNamePostfix, operation, queryName, returning, _variables });
    const fields = ['distinct_on', 'limit', 'offset', 'order_by', 'where'];
    const _returning = typeof (returning) === 'string' ? (tableName) => returning : returning;
    return (alias, index) => {
        const _a = _variables.where, { return: customReturn } = _a, where = __rest(_a, ["return"]), __variables = __rest(_variables, ["where"]);
        const variables = Object.assign(Object.assign({}, __variables), { where });
        log('generateQueryBuilder', { tableName, tableNamePostfix, operation, queryName, returning, variables, alias, index });
        const generateDefs = (fields, index, tableName, postfix = '') => {
            const fieldTypes = fieldsInputs(tableName);
            const defs = [];
            const args = [];
            for (let f = 0; f < fields.length; f++) {
                const field = fields[f];
                const key = field + index + postfix;
                defs.push(`$${key}: ${fieldTypes[field]}`);
                args.push(`${field}: $${key}`);
            }
            return { defs, args };
        };
        const { defs, args } = generateDefs(fields, index, tableName);
        const resultAlias = `${alias}${typeof (index) === 'number' ? index : ''}`;
        const resultVariables = {};
        for (const v in variables) {
            if (Object.prototype.hasOwnProperty.call(variables, v)) {
                const variable = variables[v];
                resultVariables[v + index] = variable;
            }
        }
        let customReturnAliases = ``;
        const generateCustomArgsAndVariables = (customReturn, prefix = '') => {
            for (let r in customReturn) {
                const _a = customReturn[r], { return: _return, relation, table } = _a, customWhere = __rest(_a, ["return", "relation", "table"]);
                console.log('generateCustomArgsAndVariables', table);
                const _table = table || tableName;
                const postfix = `${prefix}_${r}`;
                let customReturning = '';
                if (_return) {
                    customReturning += generateCustomArgsAndVariables(_return, postfix);
                }
                if (manyRelations[relation]) {
                    const { defs: _defs, args: _args } = generateDefs(fields, index, _table, postfix);
                    defs.push(..._defs);
                    const variable = customWhere;
                    resultVariables['where' + index + postfix] = variable;
                    return ` ${r}: ${customReturn[r].relation}(${_args.join(',')}) { ${_returning(_table)} ${customReturning} }`;
                }
                else {
                    const variable = customWhere;
                    resultVariables['where' + index + postfix] = variable;
                    return ` ${r}: ${customReturn[r].relation} { ${_returning(_table)} ${customReturning} }`;
                }
            }
            return '';
        };
        customReturnAliases += generateCustomArgsAndVariables(customReturn, '');
        const result = {
            tableName,
            tableNamePostfix,
            operation,
            queryName: queryName + tableNamePostfix,
            returning,
            variables,
            resultReturning: `${_returning(tableName)}${customReturnAliases || ''}`,
            fields,
            index,
            defs,
            args,
            alias,
            resultAlias,
            resultVariables,
        };
        log('generateQueryResult', result);
        return result;
    };
};
;
;
export const generateQuery = ({ queries = [], operation = 'query', name = 'QUERY', alias = 'q', }) => {
    log('generateQuery', { name, alias, queries });
    const calledQueries = queries.map((m, i) => typeof (m) === 'function' ? m(alias, i) : m);
    const defs = calledQueries.map(m => m.defs.join(',')).join(',');
    const queryString = `${operation} ${name} (${defs}) { ${calledQueries.map(m => `${m.resultAlias}: ${m.queryName}(${m.args.join(',')}) { ${m.resultReturning} }`).join('')} }`;
    let query;
    try {
        query = gql `${queryString}`;
    }
    catch (e) {
        throw e;
    }
    const variables = {};
    for (let a = 0; a < calledQueries.length; a++) {
        const action = calledQueries[a];
        for (const v in action.resultVariables) {
            if (Object.prototype.hasOwnProperty.call(action.resultVariables, v)) {
                const variable = action.resultVariables[v];
                variables[v] = variable;
            }
        }
    }
    const result = {
        query,
        variables,
        queryString,
    };
    log('generateQueryResult', JSON.stringify({ query: queryString, variables }, null, 2));
    return result;
};
//# sourceMappingURL=query.js.map