'use strict';

const Promise = require('bluebird');
const _ = require('lodash');
const Log = require('./log');

const resolver = module.exports = {

    entity(entity) {
        if (entity.isComponent) {
            entity = entity.variants().default();
        }
        return entity;
    },

    context(context, source) {
        const self = this;

        function resolve(obj) {
            if (!obj) {
                return Promise.resolve(null);
            }
            const iterator = _.isArray(obj) ? 'map' : 'mapValues';
            const resolver = iterator == 'map' ? 'all': 'props';

            return Promise[resolver](_[iterator](obj, mapper));
        }

        function mapper(item, key) {

            if (item === undefined || item === null) {
                return Promise.resolve(null);
            }

            if (item.then) {
                return item;
            }

            if (_.isString(item) && _.startsWith(item, '\\@')) {
                return item.replace(/^\\@/, '@');
            }

	        if (_.isString(item) && _.startsWith(item, '@@')) {
                const entity = source.find(item.substring(1));
                const fullRenderedComponent = source.engine().render(entity.viewPath, entity.content, entity.context, {
                    self: entity.toJSON(),
                    env: {},
                });
                return fullRenderedComponent;
            }

            if (_.isString(item) && _.startsWith(item, '@')) {
                const parts = item.split('.');
                const handle = parts.shift();
                let entity = source.find(handle);
                if (entity) {
                    entity = self.entity(entity);
                    if (entity._hasResolvedContext) {
                        let context = entity.getContext();
                        if (parts.length) {
                            return _.get(context, parts.join('.'), null);
                        }
                        return context;
                    } else {
                        return resolve(entity.context).then(entityContext => {
                            let clonedContext = _.cloneDeep(entityContext);
                            if (parts.length) {
                                return _.get(clonedContext, parts.join('.'), null);
                            }
                            return clonedContext;
                        });
                    }
                }
                Log.warn(`Could not resolve context reference for ${item}`);
                return null;
            }

            if (_.isArray(item) || _.isObject(item)) {
                return resolve(item);
            }

            return item;
        }

        return resolve(context).then(ctx => _.cloneDeep(ctx));
    }

};

@@ -2585,32 +2585,119 @@
 %0A            %7D%0A%0A
+            if (_.isDate(item)) %7B%0A                return item.toJSON();%0A            %7D%0A%0A
             if (

resolve date in config to JSON string (#574)