"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 entry_component_1 = require("../datalayer/entry-component");
const auth_middleware_1 = require("./auth-middleware");
const middleware_component_1 = __importDefault(require("../middleware/middleware-component"));
const connect_sequence_1 = __importDefault(require("connect-sequence"));
const datalayer_libs_1 = require("../datalayer/datalayer-libs");
/**
 * 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: entry_component_1.ENTRY_INSTANCE_TYPE,
        instanceId: props.id
    };
    const mwProps = {
        middleware: middleware_component_1.default({ callback: (req, res, next) => {
                console.log("this is the default mw of the SecuredEntry: ", props.id);
                if (securedEntryProps.externalMiddleware) {
                    console.log("now using the provided middleware");
                    return new connect_sequence_1.default(req, res, next)
                        .append(securedEntryProps.externalMiddleware.callback)
                        .run();
                }
                return next();
            } })
    };
    const securedEntryProps = {
        //origRangeKey: props.rangeKey,
        setUserId: (userId) => {
            console.log(props.id, " received userId: ", userId);
            securedEntryProps.userId = userId;
            //props.rangeKey = IC_USER_ID
        },
        /**
         * We MUST NOT OVERWRITE exisiting functions, only data. middleware is a function
         * because they get not called
         */
        // the authentication-component replaces the middleware!
        setMiddleware: (mw) => {
            console.log(props.id, " received middleware: ", mw);
            securedEntryProps.externalMiddleware = mw;
        }
    };
    const entryProps = entry_component_1.createEntryProps(Object.assign({}, props, componentProps, securedEntryProps));
    const setUserIdFromContext = (context) => {
        //console.log("check userId? ", entryProps, props, securedEntryProps)
        // when called through ssr, we do not get the userId through the ICs. But the DataLayer-Integration puts
        // it into the context for us
        if (securedEntryProps && securedEntryProps.userId) {
            console.log("SecuredEntry already has userId, not taking from context: ", securedEntryProps.userId);
            return;
        }
        if (context && context.userId) {
            if (securedEntryProps) {
                securedEntryProps["userId"] = context["userId"];
            }
            else {
                console.error("no entryProps exist, cannot set userId");
            }
            return;
        }
        console.warn("no userId in context or in entryProps...");
    };
    return Object.assign(entryProps, {
        // we need to adjust the writing into the table
        setEntry: (args, context, tableName) => {
            setUserIdFromContext(context);
            return datalayer_libs_1.setEntry(tableName, //"code-architect-dev-data-layer",
            props.primaryKey, // schema.Entry.ENTITY, //pkEntity
            args[props.primaryKey], // pkId
            auth_middleware_1.IC_USER_ID, //schema.Data.ENTITY, // skEntity
            `${securedEntryProps.userId}|${props.rangeKey}|${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
            );
        },
        listEntries: (args, context, tableName, key) => {
            setUserIdFromContext(context);
            const entity = key === "pk" ? props.primaryKey : `${auth_middleware_1.IC_USER_ID}|${securedEntryProps.userId}|${props.rangeKey}`;
            const range = key === "pk" ? `${auth_middleware_1.IC_USER_ID}|${securedEntryProps.userId}|${props.rangeKey}` : props.primaryKey;
            return datalayer_libs_1.ddbListEntries(tableName, //tablename
            key, // key
            entity, //entity
            args[key === "pk" ? props.primaryKey : props.rangeKey], //value
            range //rangeEntity
            ).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;
                });
            });
        },
    }, mwProps);
    // we provide the newly set middleware as last prop to overwrite the other values!
};
exports.isSecuredEntry = (component) => {
    return component !== undefined && component.instanceType === entry_component_1.ENTRY_INSTANCE_TYPE;
};
const complementedProps = {
/*
 createEntryFields: () => {
 const fields = Object.keys(props.data).reduce((result, key)=> {
 if (key !== securedEntryProps.origRangeKey) {
 result[key] = {type: props.data[key]};
 }


 return result;
 }, {});

 fields[props.primaryKey] = {type: GraphQLString};
 fields[IC_USER_ID] = {type: GraphQLString};

 return fields;
 },

 createEntryType: (prefix) => {
 return new GraphQLObjectType({
 name: prefix+props.id,
 fields: () => complementedProps.createEntryFields()
 })
 },

 createKeyArgs: () => {

 const args = {};

 args[props.primaryKey] = {name: props.primaryKey, type: GraphQLString};
 args[IC_USER_ID] = {name: IC_USER_ID, type: GraphQLString};

 return args;
 },* /

 getEntryListQuery: (dictKey) => {
 const fields = entryProps.createEntryFields();
 //console.log("fields: ", fields);

 return getEntryListQuery(
 props.id,
 dictKey,
 fields,
 {
 userId: securedEntryProps.userId
 } //context
 );
 },

 setEntryMutation: (values) => {
 const fields = entryProps.createEntryFields();
 //console.log("fields: ", fields);

 return setEntryMutation(
 props.id,
 values,
 fields,
 {
 userId: securedEntryProps.userId
 } //context
 );

 },

 /*

 // let's overwrite how the user can get the
 getEntryListQuery: (dictKey) => {
 const fields = complementedProps.createEntryFields();
 //console.log("fields: ", fields);

 // TODO, complement dictKey or even change the whole query ...
 return getEntryListQuery(
 props.id,
 Object.keys(dictKey).reduce((res, key) => {
 // we replace the rangeKey with the
 if (key === securedEntryProps.origRangeKey) {
 res[props.rangeKey] = `${securedEntryProps.clientId}|${securedEntryProps.origRangeKey}|${dictKey[key]}`
 } else {
 res[key] = dictKey[key];
 }
 return res;
 }, {}),
 fields
 );
 },

 // this creates the input for the gql-tag: how the query is sent to apollo
 setEntryMutation: (values) => {
 const fields = complementedProps.createEntryFields();


 return setEntryMutation(
 props.id,
 Object.keys(values).reduce((res, key) => {
 // we replace the rangeKey with the
 if (key === securedEntryProps.origRangeKey) {
 res[props.rangeKey] = `${securedEntryProps.clientId}|${securedEntryProps.origRangeKey}|${values[key]}`
 } else {
 res[key] = values[key];
 }
 return res;
 }, {}),
 fields,
 {
 // we need to pass the clientId into the context of the gql-query for we don't have the value there yet!
 clientId: securedEntryProps.clientId
 } //context
 );
 }*/
};
//# sourceMappingURL=securedentry-component.js.map