"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const types_1 = __importDefault(require("../types"));
const datalayer_libs_1 = require("./datalayer-libs");
const middleware_component_1 = __importDefault(require("../middleware/middleware-component"));
const graphql_1 = require("graphql");
exports.ENTRY_INSTANCE_TYPE = "EntryComponent";
;
exports.createEntryProps = (props) => {
    const entryProps = {
        createEntryFields: () => {
            const fields = Object.keys(props.data).reduce((result, key) => {
                result[key] = { type: props.data[key] };
                return result;
            }, {});
            if (props.primaryKey) {
                fields[props.primaryKey] = { type: graphql_1.GraphQLString };
            }
            if (props.rangeKey) {
                fields[props.rangeKey] = { type: graphql_1.GraphQLString };
            }
            return fields;
        },
        createEntryType: (prefix) => {
            return new graphql_1.GraphQLObjectType({
                name: prefix + props.id,
                fields: () => entryProps.createEntryFields()
            });
        },
        createKeyArgs: () => {
            const args = {};
            if (props.primaryKey) {
                args[props.primaryKey] = { name: props.primaryKey, type: graphql_1.GraphQLString };
            }
            if (props.rangeKey) {
                args[props.rangeKey] = { name: props.rangeKey, type: graphql_1.GraphQLString };
            }
            return args;
        },
        createEntryArgs: () => {
            const args = Object.keys(props.data).reduce((result, key) => {
                result[key] = { name: key, type: graphql_1.GraphQLString };
                return result;
            }, {});
            if (props.primaryKey) {
                args[props.primaryKey] = { name: props.primaryKey, type: graphql_1.GraphQLString };
            }
            if (props.rangeKey) {
                args[props.rangeKey] = { name: props.rangeKey, type: graphql_1.GraphQLString };
            }
            return args;
        },
        getEntryListQuery: (dictKey) => {
            const fields = entryProps.createEntryFields();
            //console.log("fields: ", fields);
            return datalayer_libs_1.getEntryListQuery(props.id, dictKey, fields);
        },
        getEntryQuery: (dictKey) => {
            const fields = entryProps.createEntryFields();
            //console.log("fields: ", fields);
            return datalayer_libs_1.getEntryQuery(props.id, dictKey, fields);
        },
        getEntryScanQuery: (dictKey) => {
            const fields = entryProps.createEntryFields();
            //console.log("fields: ", fields);
            return datalayer_libs_1.getEntryScanQuery(props.id, dictKey, fields);
        },
        setEntryMutation: (values) => {
            const fields = entryProps.createEntryFields();
            //console.log("fields: ", fields);
            return datalayer_libs_1.setEntryMutation(props.id, values, fields);
        },
        setEntry: (args, context, tableName, isOffline) => {
            //console.log("setEntry: ", args, "offline: ", isOffline);
            return datalayer_libs_1.setEntry(tableName, //"code-architect-dev-data-layer",
            props.primaryKey, // schema.Entry.ENTITY, //pkEntity
            args[props.primaryKey], // pkId
            props.rangeKey, //schema.Data.ENTITY, // skEntity
            args[props.rangeKey], // skId
            Object.keys(args).reduce((result, key) => {
                if (Object.keys(props.data).find(datakey => datakey === key) !== undefined) {
                    result[key] = args[key];
                }
                return result;
            }, {}), // jsonData
            isOffline // do we run offline?
            );
        },
        listEntries: (args, context, tableName, key, isOffline) => {
            const entity = key === "pk" ? props.primaryKey : props.rangeKey;
            const range = key === "pk" ? props.rangeKey : props.primaryKey;
            //console.log("listEntries: offline? ", isOffline)
            return datalayer_libs_1.ddbListEntries(tableName, //tablename
            key, // key
            entity, //entity
            args[entity], //value
            range, //rangeEntity
            isOffline).then(results => {
                //console.log("promised: ", results);
                return results.map(item => {
                    const data = item.jsonData !== undefined ? JSON.parse(item.jsonData) : {};
                    data[props.primaryKey] = item.pk.substring(item.pk.indexOf("|") + 1);
                    data[props.rangeKey] = item.sk.substring(item.sk.indexOf("|") + 1);
                    return data;
                });
            });
        },
        getEntry: (args, context, tableName, isOffline) => {
            return datalayer_libs_1.ddbGetEntry(tableName, //tablename
            props.primaryKey, // pkEntity,
            args[props.primaryKey], // pkValue,
            props.rangeKey, // skEntity,
            args[props.rangeKey], // skValue
            isOffline).then((result) => {
                //console.log("entry-component getEntry result: ", result);
                const data = result.jsonData !== undefined ? JSON.parse(result.jsonData) : {};
                if (result && result.pk && result.sk) {
                    data[props.primaryKey] = result.pk.substring(result.pk.indexOf("|") + 1);
                    data[props.rangeKey] = result.sk.substring(result.sk.indexOf("|") + 1);
                }
                return data;
            });
        },
        scan: (args, context, tableName, key, isOffline) => {
            //console.log("scan entry! ", args,  "offline: ", isOffline)
            return datalayer_libs_1.ddbScan(tableName, //tablename
            key, // key
            key === "pk" ? props.primaryKey : props.rangeKey, // pkEntity,
            args.scanall ? undefined : args[`start_${key === "pk" ? props.primaryKey : props.rangeKey}`], // start_value,
            args.scanall ? undefined : args[`end_${key === "pk" ? props.primaryKey : props.rangeKey}`], // end_Value,
            key === "pk" ? props.rangeKey : props.primaryKey, // skEntity,
            isOffline).then((result) => {
                //console.log("entry-component scan result: ", result);
                return result.map(entry => {
                    //console.log("scanned entry: ", entry);
                    const data = entry.jsonData !== undefined ? JSON.parse(entry.jsonData) : {};
                    if (entry && entry.pk && entry.sk) {
                        data[props.primaryKey] = entry.pk.substring(entry.pk.indexOf("|") + 1);
                        data[props.rangeKey] = entry.sk.substring(entry.sk.indexOf("|") + 1);
                    }
                    //console.log("returned data: ", data);
                    return data;
                });
            });
        },
        deleteEntryMutation: (values) => {
            const fields = entryProps.createEntryFields();
            //const fields = entryProps.createEntryFields();
            //console.log("fields: ", fields);
            return datalayer_libs_1.deleteEntryMutation(props.id, values, fields);
        },
        deleteEntry: (args, context, tableName, isOffline) => {
            return datalayer_libs_1.deleteEntry(tableName, //"code-architect-dev-data-layer",
            props.primaryKey, // schema.Entry.ENTITY, //pkEntity
            args[props.primaryKey], // pkId
            props.rangeKey, //schema.Data.ENTITY, // skEntity
            args[props.rangeKey], // skId
            isOffline);
        },
        middleware: middleware_component_1.default({ callback: (req, res, next) => {
                //console.log("this is the mw of the entry: ", props.id)
                return next();
            } }),
        getPrimaryListQueryName: () => "list_" + props.id + "_" + props.primaryKey,
        getRangeListQueryName: () => "list_" + props.id + "_" + props.rangeKey,
        getGetQueryName: () => "get_" + props.id,
        getSetMutationName: () => "set_" + props.id,
        getDeleteMutationName: () => "delete_" + props.id,
        getPrimaryScanName: () => "scan_" + props.id + "_" + props.primaryKey,
        getRangeScanName: () => "scan_" + props.id + "_" + props.rangeKey,
        getScanName: () => "scan_" + props.id,
        /**
         * Returns whether this entry provides the query/mutation with the specified name
         * @param name
         */
        providesQuery: (name) => {
            const result = name === entryProps.getPrimaryListQueryName() ||
                name === entryProps.getRangeListQueryName() ||
                name === entryProps.getSetMutationName() ||
                name === entryProps.getDeleteMutationName() ||
                name === entryProps.getPrimaryScanName() ||
                name === entryProps.getRangeScanName() ||
                name === entryProps.getScanName();
            //console.log("does ", props.id , " provide ", name, "? ", result)
            return result;
        }
    };
    return Object.assign({}, props, entryProps);
};
/**
 * an entry specifies a kind of data that can be stored in a line of the table
 */
exports.default = (props) => {
    // the component must have the properties of IComponent
    const componentProps = {
        infrastructureType: types_1.default.INFRASTRUCTURE_TYPE_COMPONENT,
        instanceType: exports.ENTRY_INSTANCE_TYPE,
        instanceId: props.id
    };
    return exports.createEntryProps(Object.assign({}, props, componentProps));
};
exports.isEntry = (component) => {
    return component !== undefined && component.instanceType === exports.ENTRY_INSTANCE_TYPE;
};
//# sourceMappingURL=entry-component.js.map