"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const graphql_1 = require("graphql");
const types_1 = __importDefault(require("../types"));
const libs_1 = require("../libs");
const entry_component_1 = require("./entry-component");
const datalayer_libs_1 = require("./datalayer-libs");
exports.DATALAYER_INSTANCE_TYPE = "DataLayerComponent";
;
/**
 * identifies a component as a DataLayer
 *
 * @param component to be tested
 */
function isDataLayer(component) {
    return component !== undefined && component.instanceType === exports.DATALAYER_INSTANCE_TYPE;
}
exports.isDataLayer = isDataLayer;
;
exports.default = (props) => {
    const componentProps = {
        infrastructureType: types_1.default.INFRASTRUCTURE_TYPE_COMPONENT,
        instanceType: exports.DATALAYER_INSTANCE_TYPE,
        instanceId: props.id
    };
    //const listEntities = getChildrenArray(props).filter(child => isEntity(child));
    //const entries = getChildrenArray(props).filter(child => isEntry(child));
    const entries = libs_1.findComponentRecursively(props.children, entry_component_1.isEntry);
    /**
     * create the
     * @type {{queries: {}, mutations: {}}}
     */
    const datalayerProps = {
        entries: entries,
        mutations: (resolveWithData) => entries.reduce((result, entry) => {
            result[entry.getSetMutationName()] = {
                args: entry.createEntryArgs(),
                type: entry.createEntryType("set_"),
                resolve: (source, args, context, info) => {
                    if (!resolveWithData) {
                        return entry.id;
                    }
                    console.log("resolve: ", resolveWithData, source, context, info, args);
                    // This context gets the data from the context put into the <Query/> or Mutation...
                    console.log("context: ", context);
                    const result = entry.setEntry(args, context, process.env.TABLE_NAME);
                    console.log("result: ", result);
                    return result;
                }
            };
            console.log("mutation definition: ", result["set_" + entry.id]);
            return result;
        }, {}),
        queries: (resolveWithData) => entries.reduce((result, entry) => {
            const listType = entry.createEntryType("list_");
            console.log("listType: ", listType);
            // list all the items, specifying the primaryKey
            const inputArgs = {};
            inputArgs[entry.primaryKey] = { name: entry.primaryKey, type: new graphql_1.GraphQLNonNull(graphql_1.GraphQLString) };
            result[entry.getPrimaryListQueryName()] = {
                args: inputArgs,
                type: resolveWithData ? new graphql_1.GraphQLList(listType) : listType,
                resolve: (source, args, context, info) => {
                    console.log("resolve: ", resolveWithData, source, args, context);
                    if (!resolveWithData) {
                        return entry.id;
                    }
                    return entry.listEntries(args, context, process.env.TABLE_NAME, "pk");
                    /*
                    return ddbListEntries(
                        process.env.TABLE_NAME, //tablename
                        "pk", // key
                        entry.primaryKey, //entity
                        args[entry.primaryKey], //value
                        entry.rangeKey //rangeEntity
                    ).then(results => {

                        console.log("promised: ", results);
                        return results.map(item => {
                            const data = item.jsonData !== undefined ? JSON.parse(item.jsonData) : {};
                            data[entry.primaryKey] = item.pk.substring(item.pk.indexOf("|")+1);
                            data[entry.rangeKey] = item.sk.substring(item.sk.indexOf("|")+1);
                            return data;
                        });

                    });*/
                }
            };
            // list all the items, specifying the RANGE
            const inputRangeArgs = {};
            inputRangeArgs[entry.rangeKey] = { name: entry.rangeKey, type: new graphql_1.GraphQLNonNull(graphql_1.GraphQLString) };
            result[entry.getRangeListQueryName()] = {
                args: inputRangeArgs,
                type: resolveWithData ? new graphql_1.GraphQLList(listType) : listType,
                resolve: (source, args, context, info) => {
                    console.log("resolve: ", resolveWithData, source, args, context);
                    if (!resolveWithData) {
                        return entry.id;
                    }
                    return entry.listEntries(args, context, process.env.TABLE_NAME, "sk");
                    /*
                    return ddbListEntries(
                        process.env.TABLE_NAME, //tablename
                        "sk", // key
                        entry.rangeKey, //entity
                        args[entry.rangeKey], //value
                        entry.primaryKey //rangeEntity
                    ).then(results => {

                        console.log("promised: ", results);
                        return results.map(item => {
                            const data = item.jsonData !== undefined ? JSON.parse(item.jsonData) : {};
                            data[entry.primaryKey] = item.pk.substring(item.pk.indexOf("|")+1);
                            data[entry.rangeKey] = item.sk.substring(item.sk.indexOf("|")+1);
                            return data;
                        });

                    });*/
                }
            };
            return result;
        }, {}),
        /*
        getEntryDataFields: (entryId) => {
            const entry = entries.find(entry => entry.id === entryId);
            if (entry !== undefined) {
                return entry.createEntryFields()
            };

            console.warn("could not find entry: ",entryId);
            return {};
        },*/
        // TODO forward this request to the Entry and let the entry handle the whole request!
        getEntryListQuery: (entryId, dictKey) => {
            const entry = entries.find(entry => entry.id === entryId);
            if (entry !== undefined) {
                return entry.getEntryListQuery(dictKey);
            }
            ;
            console.warn("could not find entry: ", entryId);
            return {};
            /*
             const fields = datalayerProps.getEntryDataFields(entryId);
             //console.log("fields: ", fields);

             return getEntryListQuery(
                 entryId,
                 dictKey,
                 fields
             );*/
        },
        setEntryMutation: (entryId, values) => {
            const entry = entries.find(entry => entry.id === entryId);
            if (entry !== undefined) {
                return entry.setEntryMutation(values);
            }
            ;
            console.warn("could not find entry: ", entryId);
            return {};
        },
    };
    const schemaProps = {
        getSchema: (resolveWithData) => new graphql_1.GraphQLSchema({
            query: new graphql_1.GraphQLObjectType({
                name: 'RootQueryType',
                fields: datalayerProps.queries(resolveWithData)
            }), mutation: new graphql_1.GraphQLObjectType({
                name: 'RootMutationType',
                fields: datalayerProps.mutations(resolveWithData)
            })
        })
    };
    // we need to provide the DataLayerId to webApps, these may be anywhere in the tree, not
    // only direct children. So rather than mapping the children, we need to change them
    libs_1.findComponentRecursively(props.children, (child) => child.setDataLayerId !== undefined).forEach(child => {
        child.setDataLayerId(props.id);
    });
    libs_1.findComponentRecursively(props.children, (child) => child.setStoreData !== undefined).forEach(child => {
        child.setStoreData(function (pkEntity, pkVal, skEntity, skVal, jsonData) {
            return __awaiter(this, void 0, void 0, function* () {
                return yield datalayer_libs_1.setEntry(process.env.TABLE_NAME, //"code-architect-dev-data-layer",
                pkEntity, // schema.Entry.ENTITY, //pkEntity
                pkVal, // pkId
                skEntity, //schema.Data.ENTITY, // skEntity
                skVal, // skId
                jsonData // jsonData
                );
            });
        });
    });
    return Object.assign({}, props, componentProps, datalayerProps, schemaProps);
};
//# sourceMappingURL=datalayer-component.js.map