"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Controller = void 0;
var base_controller_1 = require("lynx-framework/base.controller");
var decorators_1 = require("./decorators");
var media_entity_1 = require("lynx-framework/entities/media.entity");
var generator_1 = require("./generator");
var typeorm_1 = require("typeorm");
var moment = require("moment");
var datagrid_1 = require("lynx-datagrid/datagrid");
var _1 = require(".");
var _adminUI;
var hasInit = false;
var Controller = /** @class */ (function (_super) {
    __extends(Controller, _super);
    function Controller() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Controller.saveEntity = function (entity, req) {
        return __awaiter(this, void 0, void 0, function () {
            var updated;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!entity.onBeforeSave) return [3 /*break*/, 2];
                        return [4 /*yield*/, entity.onBeforeSave(req)];
                    case 1:
                        _a.sent();
                        _a.label = 2;
                    case 2: return [4 /*yield*/, entity.save()];
                    case 3:
                        updated = _a.sent();
                        if (!updated.onAfterSave) return [3 /*break*/, 5];
                        return [4 /*yield*/, updated.onAfterSave(req)];
                    case 4:
                        _a.sent();
                        _a.label = 5;
                    case 5: return [2 /*return*/, updated];
                }
            });
        });
    };
    Controller.prototype.postConstructor = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, _super.prototype.postConstructor.call(this)];
                    case 1:
                        _a.sent();
                        if (!hasInit) {
                            hasInit = true;
                            _adminUI = generator_1.generateSchema(this.app.config.db.entities);
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    Object.defineProperty(Controller.prototype, "adminUI", {
        get: function () {
            return _adminUI;
        },
        enumerable: false,
        configurable: true
    });
    Controller.prototype.entitiesList = function () {
        var list = [];
        for (var _i = 0, _a = this.adminUI; _i < _a.length; _i++) {
            var d = _a[_i];
            list.push({
                name: d.entity.name,
                readableName: d.meta.name,
            });
        }
        return list;
    };
    Controller.prototype.retrieveEntity = function (entityName, id) {
        return __awaiter(this, void 0, void 0, function () {
            var _i, _a, d;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _i = 0, _a = this.adminUI;
                        _b.label = 1;
                    case 1:
                        if (!(_i < _a.length)) return [3 /*break*/, 4];
                        d = _a[_i];
                        if (!(d.entity.name == entityName)) return [3 /*break*/, 3];
                        if (!id || id == '0') {
                            return [2 /*return*/, new d.entity()];
                        }
                        return [4 /*yield*/, d.entity.findOne(id, {
                                relations: d.meta.classParameters.relations,
                            })];
                    case 2: return [2 /*return*/, _b.sent()];
                    case 3:
                        _i++;
                        return [3 /*break*/, 1];
                    case 4: return [2 /*return*/, null];
                }
            });
        });
    };
    Controller.prototype.retrieveEntityClass = function (entityName) {
        for (var _i = 0, _a = this.adminUI; _i < _a.length; _i++) {
            var d = _a[_i];
            if (d.entity.name == entityName) {
                return d.entity;
            }
        }
        return null;
    };
    Controller.prototype.retrieveMetadata = function (entityName) {
        for (var _i = 0, _a = this.adminUI; _i < _a.length; _i++) {
            var d = _a[_i];
            if (d.entity.name == entityName) {
                return d.meta;
            }
        }
        return null;
    };
    Controller.prototype.retrieveData = function (req, entityName, id) {
        return __awaiter(this, void 0, void 0, function () {
            var current;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.retrieveEntity(entityName, id)];
                    case 1:
                        current = _a.sent();
                        if (!current) {
                            if (!id || id == 0) {
                                return [2 /*return*/, new (this.retrieveEntityClass(entityName))()];
                            }
                            return [2 /*return*/, null];
                        }
                        return [4 /*yield*/, this.cleanData(req, current, this.retrieveMetadata(entityName))];
                    case 2: return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    Controller.prototype.retrieveList = function (req, entityName, datagrid) {
        return __awaiter(this, void 0, void 0, function () {
            var Class, metadata, filterWhere, where, smartWhere, qb, hasCustomFetchData, disableReload, filterCounter, hasSmart, key, f, v, right, left, Class_1, repository, ors, key, tmp, key, tmp, _i, _a, relation, _b, where_1, orOption, parts, params, counter, key, _q, value, i, _v, _v, _v, q, tmp, promises_1, _c;
            var _this = this;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0:
                        Class = this.retrieveEntityClass(entityName);
                        if (!Class) {
                            return [2 /*return*/, null];
                        }
                        metadata = this.retrieveMetadata(entityName);
                        filterWhere = null;
                        if (!metadata.classParameters.filterBy) return [3 /*break*/, 2];
                        return [4 /*yield*/, metadata.classParameters.filterBy(req)];
                    case 1:
                        filterWhere = _d.sent();
                        _d.label = 2;
                    case 2:
                        where = {};
                        smartWhere = {};
                        qb = null;
                        hasCustomFetchData = (metadata.classParameters.customFetchData !==
                            undefined);
                        disableReload = metadata.classParameters
                            .disableReloadOnList;
                        if (!hasCustomFetchData) {
                            filterCounter = 0;
                            hasSmart = false;
                            for (key in metadata.fields) {
                                f = metadata.fields[key];
                                if (!f.searchable && !f.smartSearchable) {
                                    continue;
                                }
                                v = null;
                                if (f.searchable) {
                                    v = datagrid.getQueryValue(key);
                                    if (v) {
                                        filterCounter += 1;
                                    }
                                }
                                else if (f.smartSearchable) {
                                    v = datagrid.getQueryValue('smartSearch');
                                    if (v && !hasSmart) {
                                        hasSmart = true;
                                        filterCounter += 1;
                                    }
                                }
                                if (v) {
                                    right = void 0;
                                    left = '';
                                    if (f.type == decorators_1.AdminType.String) {
                                        right = typeorm_1.Like('%' + v.toLowerCase() + '%');
                                        key = 'e.' + key;
                                    }
                                    else {
                                        Class_1 = this.retrieveEntityClass(f.selfType);
                                        if (Class_1) {
                                            if ((metadata.classParameters.relations || []).indexOf(key) == -1) {
                                                this.logger.error('Searching for the column `' +
                                                    key +
                                                    '` is enabled only if `' +
                                                    key +
                                                    '` is specified in the `relations` parmeter of `AdminUI`');
                                                throw new Error('The `relation` field of AdminUI not include ' +
                                                    key);
                                            }
                                            right = v;
                                            key = key.toUpperCase();
                                            left = '.id';
                                        }
                                        else {
                                            right = v;
                                            key = 'e.' + key;
                                        }
                                    }
                                    if (f.smartSearchable) {
                                        smartWhere[key + left] = right;
                                    }
                                    else {
                                        where[key + left] = right;
                                    }
                                }
                            }
                            req.__admin_ui_filterCounter = filterCounter;
                            repository = typeorm_1.getConnection().getRepository(Class);
                            ors = [];
                            if (Object.keys(smartWhere).length > 0) {
                                for (key in smartWhere) {
                                    tmp = __assign(__assign({}, filterWhere), where);
                                    tmp[key] = smartWhere[key];
                                    ors.push(tmp);
                                }
                            }
                            else {
                                for (key in where) {
                                    tmp = __assign({}, filterWhere);
                                    tmp[key] = where[key];
                                    ors.push(tmp);
                                }
                            }
                            where = ors;
                            qb = repository.createQueryBuilder('e');
                            for (_i = 0, _a = metadata.classParameters.relations || []; _i < _a.length; _i++) {
                                relation = _a[_i];
                                qb = qb.leftJoinAndSelect('e.' + relation, relation.toUpperCase());
                            }
                            for (_b = 0, where_1 = where; _b < where_1.length; _b++) {
                                orOption = where_1[_b];
                                parts = [];
                                params = {};
                                counter = 0;
                                for (key in orOption) {
                                    _q = '';
                                    value = orOption[key];
                                    if (value instanceof Array) {
                                        _q += '(';
                                        for (i = 0; i < value.length; i++) {
                                            _v = 'param' + counter;
                                            params[_v] = value[i];
                                            counter++;
                                            _q += key + ' = :' + _v;
                                            if (i < value.length - 1) {
                                                _q += ' OR';
                                            }
                                            _q += ' ';
                                        }
                                        _q += ') ';
                                    }
                                    else if (value instanceof typeorm_1.FindOperator) {
                                        _v = 'param' + counter;
                                        params[_v] = value.value;
                                        counter++;
                                        _q += key + ' LIKE :' + _v + ' ';
                                    }
                                    else {
                                        _v = 'param' + counter;
                                        params[_v] = value;
                                        counter++;
                                        _q += key + ' = :' + _v + ' ';
                                    }
                                    parts.push(_q.trim());
                                }
                                q = parts.join(' AND ');
                                qb = qb.orWhere(q, params);
                            }
                        }
                        return [4 /*yield*/, datagrid.fetchData(function (params) {
                                var order = params.order;
                                if (hasCustomFetchData) {
                                    return (metadata.classParameters.customFetchData &&
                                        metadata.classParameters.customFetchData(req, params.order, params.take, params.skip));
                                }
                                if (Object.keys(order).length == 0 &&
                                    metadata.classParameters.defaultOrderBy) {
                                    var tmp = metadata.classParameters.defaultOrderBy;
                                    if (tmp.startsWith('-')) {
                                        order[tmp.substring(1)] = 'ASC';
                                    }
                                    else if (tmp.startsWith('+')) {
                                        order[tmp.substring(1)] = 'DESC';
                                    }
                                    else {
                                        order[tmp] = 'DESC';
                                    }
                                }
                                for (var key in order) {
                                    qb = qb.addOrderBy('e.' + key, order[key]);
                                }
                                qb = qb.skip(params.skip);
                                qb = qb.take(params.take);
                                return qb.getManyAndCount();
                            })];
                    case 3:
                        _d.sent();
                        if (!!disableReload) return [3 /*break*/, 5];
                        tmp = datagrid.data;
                        promises_1 = [];
                        tmp.forEach(function (t) { return promises_1.push(t.reload()); });
                        return [4 /*yield*/, Promise.all(promises_1)];
                    case 4:
                        _d.sent();
                        _d.label = 5;
                    case 5:
                        _c = datagrid;
                        return [4 /*yield*/, Promise.all(datagrid.data.map(function (d) { return _this.cleanData(req, d, metadata, true); }))];
                    case 6:
                        _c.data = _d.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    Controller.prototype.cleanData = function (req, _data, metadata, forList) {
        var _a;
        return __awaiter(this, void 0, void 0, function () {
            var obj, data, defaultValues, _loop_1, this_1, _b, _c, _i, key;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0:
                        obj = {};
                        data = _data;
                        defaultValues = {};
                        if (req.query.defaultValues) {
                            defaultValues = JSON.parse(req.query.defaultValues);
                        }
                        _loop_1 = function (key) {
                            var executor_1, datagrid, gridMetadata, i, _a, _b, entityClass, _c, _d, _e, _f, ee, nestedMeta, cleanData, k, ee;
                            return __generator(this, function (_g) {
                                switch (_g.label) {
                                    case 0:
                                        if (forList) {
                                            if (metadata.fields[key].onSummary !== true) {
                                                return [2 /*return*/, "continue"];
                                            }
                                        }
                                        if (!metadata.fields[key].query) return [3 /*break*/, 6];
                                        executor_1 = metadata.fields[key].query;
                                        datagrid = new datagrid_1.default(key + '-', req);
                                        return [4 /*yield*/, datagrid.fetchData(function (params) {
                                                return executor_1(req, data, params);
                                            })];
                                    case 1:
                                        _g.sent();
                                        gridMetadata = this_1.retrieveMetadata(metadata.fields[key].selfType);
                                        if (!gridMetadata) return [3 /*break*/, 5];
                                        i = 0;
                                        _g.label = 2;
                                    case 2:
                                        if (!(i < datagrid.data.length)) return [3 /*break*/, 5];
                                        _a = datagrid.data;
                                        _b = i;
                                        return [4 /*yield*/, this_1.cleanData(req, datagrid.data[i], gridMetadata, true)];
                                    case 3:
                                        _a[_b] = _g.sent();
                                        _g.label = 4;
                                    case 4:
                                        i++;
                                        return [3 /*break*/, 2];
                                    case 5:
                                        obj[key] = datagrid;
                                        obj[key + '__disable_creation'] = false;
                                        if (metadata.fields[key].max) {
                                            if (datagrid.length >= metadata.fields[key].max) {
                                                obj[key + '__disable_creation'] = true;
                                            }
                                        }
                                        return [3 /*break*/, 17];
                                    case 6:
                                        obj[key] = data[key];
                                        if (!_data.hasId() && metadata.fields[key].defaultValue) {
                                            obj[key] = metadata.fields[key].defaultValue;
                                        }
                                        if (!defaultValues[key]) return [3 /*break*/, 9];
                                        entityClass = this_1.retrieveEntityClass((_a = metadata.fields[key].selfType) !== null && _a !== void 0 ? _a : '');
                                        if (!entityClass) return [3 /*break*/, 8];
                                        _c = obj;
                                        _d = key;
                                        return [4 /*yield*/, this_1.retrieveEntity(metadata.fields[key].selfType, defaultValues[key])];
                                    case 7:
                                        _c[_d] = _g.sent();
                                        return [3 /*break*/, 9];
                                    case 8:
                                        obj[key] = defaultValues[key];
                                        _g.label = 9;
                                    case 9:
                                        if (!(obj[key] instanceof Object)) return [3 /*break*/, 17];
                                        if (!(obj[key] instanceof Promise && obj[key])) return [3 /*break*/, 11];
                                        _e = obj;
                                        _f = key;
                                        return [4 /*yield*/, obj[key]];
                                    case 10:
                                        _e[_f] = _g.sent();
                                        if (!obj[key]) {
                                            return [2 /*return*/, "continue"];
                                        }
                                        _g.label = 11;
                                    case 11:
                                        if (!(obj[key] instanceof Date)) return [3 /*break*/, 12];
                                        obj[key] = moment(data[key]);
                                        return [3 /*break*/, 17];
                                    case 12:
                                        if (!(obj[key] instanceof Array)) return [3 /*break*/, 13];
                                        if (forList) {
                                            obj[key] = obj[key].map(function (e) {
                                                return e.getLabel();
                                            });
                                        }
                                        else {
                                            obj[key] = obj[key].map(function (e) {
                                                return e.getId();
                                            });
                                        }
                                        return [3 /*break*/, 17];
                                    case 13:
                                        if (!forList) return [3 /*break*/, 14];
                                        ee = obj[key];
                                        if (ee.getLabel) {
                                            obj[key] = ee.getLabel();
                                        }
                                        return [3 /*break*/, 17];
                                    case 14:
                                        nestedMeta = this_1.retrieveMetadata(metadata.fields[key].selfType);
                                        if (!nestedMeta) return [3 /*break*/, 16];
                                        return [4 /*yield*/, this_1.cleanData(req, obj[key], nestedMeta)];
                                    case 15:
                                        cleanData = _g.sent();
                                        for (k in cleanData) {
                                            obj[key + '-' + k] = cleanData[k];
                                        }
                                        _g.label = 16;
                                    case 16:
                                        if (obj[key]) {
                                            ee = obj[key];
                                            if (ee.getId) {
                                                obj[key] = ee.getId();
                                            }
                                            else {
                                                obj[key] = obj[key].id;
                                            }
                                            if (ee instanceof media_entity_1.default) {
                                                obj[key + '__' + 'mimetype'] = ee.mimetype;
                                            }
                                        }
                                        _g.label = 17;
                                    case 17: return [2 /*return*/];
                                }
                            });
                        };
                        this_1 = this;
                        _b = [];
                        for (_c in metadata.fields)
                            _b.push(_c);
                        _i = 0;
                        _d.label = 1;
                    case 1:
                        if (!(_i < _b.length)) return [3 /*break*/, 4];
                        key = _b[_i];
                        return [5 /*yield**/, _loop_1(key)];
                    case 2:
                        _d.sent();
                        _d.label = 3;
                    case 3:
                        _i++;
                        return [3 /*break*/, 1];
                    case 4:
                        obj.getLabel = function () {
                            return _data.getLabel();
                        };
                        obj.getId = function () {
                            return _data.getId();
                        };
                        return [2 /*return*/, obj];
                }
            });
        });
    };
    Controller.prototype.setData = function (req, entity, data, metadata, prefix) {
        var _a, _b;
        if (prefix === void 0) { prefix = ''; }
        return __awaiter(this, void 0, void 0, function () {
            var _loop_2, this_2, _c, _d, _i, key;
            return __generator(this, function (_e) {
                switch (_e.label) {
                    case 0:
                        _loop_2 = function (key) {
                            var m, r, originalMeta, _a, _b, values, v, _class, _c, _d, updated, _loop_3, _i, _e, id, entityClass, e, _f, _g, _h, _j, currentMeta, old, _k, _l, f, file;
                            return __generator(this, function (_m) {
                                switch (_m.label) {
                                    case 0:
                                        m = metadata.fields[key];
                                        if (!(m.readOnly instanceof Function)) return [3 /*break*/, 2];
                                        return [4 /*yield*/, m.readOnly(req, entity)];
                                    case 1:
                                        r = _m.sent();
                                        if (r) {
                                            return [2 /*return*/, "continue"];
                                        }
                                        return [3 /*break*/, 3];
                                    case 2:
                                        if (m.readOnly) {
                                            return [2 /*return*/, "continue"];
                                        }
                                        _m.label = 3;
                                    case 3:
                                        originalMeta = this_2.retrieveMetadata(entity.constructor.name);
                                        if (!(m.type == decorators_1.AdminType.ActionButton &&
                                            req.body['__admin_ui_action'] == key)) return [3 /*break*/, 5];
                                        return [4 /*yield*/, entity[key](req)];
                                    case 4:
                                        _m.sent();
                                        _m.label = 5;
                                    case 5:
                                        if (!(entity[key] instanceof Promise)) return [3 /*break*/, 7];
                                        _a = entity;
                                        _b = key;
                                        return [4 /*yield*/, entity[key]];
                                    case 6:
                                        _a[_b] = _m.sent();
                                        _m.label = 7;
                                    case 7:
                                        if (!(originalMeta.fields[key].values instanceof Function)) return [3 /*break*/, 18];
                                        values = m.values;
                                        if (!(m.type == decorators_1.AdminType.Selection)) return [3 /*break*/, 12];
                                        v = values.find(function (s) { return s.key == data[prefix + key]; });
                                        if (!v) return [3 /*break*/, 11];
                                        _class = this_2.retrieveEntityClass(m.selfType);
                                        if (!!_class) return [3 /*break*/, 8];
                                        entity[key] = v.key;
                                        return [3 /*break*/, 10];
                                    case 8:
                                        _c = entity;
                                        _d = key;
                                        return [4 /*yield*/, _class.findOne(v.key)];
                                    case 9:
                                        _c[_d] = _m.sent();
                                        _m.label = 10;
                                    case 10: return [3 /*break*/, 12];
                                    case 11:
                                        entity[key] = null;
                                        _m.label = 12;
                                    case 12:
                                        if (!(m.type == decorators_1.AdminType.Checkbox)) return [3 /*break*/, 17];
                                        updated = [];
                                        if (!(data[prefix + key] && data[prefix + key].length > 0)) return [3 /*break*/, 16];
                                        _loop_3 = function (id) {
                                            var v, _a, _b;
                                            return __generator(this, function (_c) {
                                                switch (_c.label) {
                                                    case 0:
                                                        v = values.find(function (s) { return s.key == id; });
                                                        if (!v) return [3 /*break*/, 2];
                                                        _b = (_a = updated).push;
                                                        return [4 /*yield*/, this_2.retrieveEntityClass(m.selfType).findOne(v.key)];
                                                    case 1:
                                                        _b.apply(_a, [_c.sent()]);
                                                        _c.label = 2;
                                                    case 2: return [2 /*return*/];
                                                }
                                            });
                                        };
                                        _i = 0, _e = data[prefix + key];
                                        _m.label = 13;
                                    case 13:
                                        if (!(_i < _e.length)) return [3 /*break*/, 16];
                                        id = _e[_i];
                                        return [5 /*yield**/, _loop_3(id)];
                                    case 14:
                                        _m.sent();
                                        _m.label = 15;
                                    case 15:
                                        _i++;
                                        return [3 /*break*/, 13];
                                    case 16:
                                        entity[key] = updated;
                                        _m.label = 17;
                                    case 17: return [3 /*break*/, 35];
                                    case 18:
                                        if (!(m.type == decorators_1.AdminType.Checkbox)) return [3 /*break*/, 19];
                                        entity[key] = data[prefix + key] ? true : false;
                                        return [3 /*break*/, 35];
                                    case 19:
                                        if (!(m.type == decorators_1.AdminType.Expanded ||
                                            (m.type == decorators_1.AdminType.ExpandedAndSelection &&
                                                !((_a = m.optionalParameters) === null || _a === void 0 ? void 0 : _a.readOnlyExpanded)))) return [3 /*break*/, 28];
                                        return [4 /*yield*/, this_2.retrieveEntityClass(m.selfType)];
                                    case 20:
                                        entityClass = _m.sent();
                                        if (!entityClass) {
                                            return [2 /*return*/, "continue"];
                                        }
                                        e = entity;
                                        if (!!e[key]) return [3 /*break*/, 23];
                                        if (!data[key]) return [3 /*break*/, 22];
                                        _f = e;
                                        _g = key;
                                        return [4 /*yield*/, this_2.retrieveEntity(m.selfType, data[key])];
                                    case 21:
                                        _f[_g] = _m.sent();
                                        _m.label = 22;
                                    case 22:
                                        if (!e[key]) {
                                            e[key] = new entityClass();
                                        }
                                        return [3 /*break*/, 25];
                                    case 23:
                                        if (!data[key]) return [3 /*break*/, 25];
                                        _h = e;
                                        _j = key;
                                        return [4 /*yield*/, this_2.retrieveEntity(m.selfType, data[key])];
                                    case 24:
                                        _h[_j] = (_b = (_m.sent())) !== null && _b !== void 0 ? _b : e[key];
                                        _m.label = 25;
                                    case 25:
                                        currentMeta = this_2.retrieveMetadata(m.selfType);
                                        return [4 /*yield*/, this_2.setData(req, e[key], data, currentMeta, prefix + key + '-')];
                                    case 26:
                                        _m.sent();
                                        return [4 /*yield*/, Controller.saveEntity(e[key], req)];
                                    case 27:
                                        _m.sent();
                                        return [3 /*break*/, 35];
                                    case 28:
                                        if (!(m.type == decorators_1.AdminType.Media)) return [3 /*break*/, 34];
                                        if (!(data['remove-' + prefix + key] == prefix + key)) return [3 /*break*/, 29];
                                        old = entity[prefix + key];
                                        if (old) {
                                            entity[prefix + key] = null;
                                        }
                                        return [3 /*break*/, 33];
                                    case 29:
                                        _k = 0, _l = req.files;
                                        _m.label = 30;
                                    case 30:
                                        if (!(_k < _l.length)) return [3 /*break*/, 33];
                                        f = _l[_k];
                                        if (!(f.fieldname == prefix + key)) return [3 /*break*/, 32];
                                        return [4 /*yield*/, media_entity_1.default.persist(f, req.user)];
                                    case 31:
                                        file = _m.sent();
                                        entity[prefix + key] = file;
                                        return [3 /*break*/, 33];
                                    case 32:
                                        _k++;
                                        return [3 /*break*/, 30];
                                    case 33: return [3 /*break*/, 35];
                                    case 34:
                                        if (m.type == decorators_1.AdminType.AjaxSelection &&
                                            data[prefix + key] == '0') {
                                            entity[key] = null;
                                        }
                                        else {
                                            if ((m.selfType == 'Number' || m.selfType == 'Date') &&
                                                data[prefix + key] === '') {
                                                data[prefix + key] = null;
                                            }
                                            else {
                                                if (m.selfType == 'Number') {
                                                    data[prefix + key] = Number(data[prefix + key]);
                                                }
                                                entity[key] = data[prefix + key];
                                            }
                                        }
                                        _m.label = 35;
                                    case 35: return [2 /*return*/];
                                }
                            });
                        };
                        this_2 = this;
                        _c = [];
                        for (_d in metadata.fields)
                            _c.push(_d);
                        _i = 0;
                        _e.label = 1;
                    case 1:
                        if (!(_i < _c.length)) return [3 /*break*/, 4];
                        key = _c[_i];
                        return [5 /*yield**/, _loop_2(key)];
                    case 2:
                        _e.sent();
                        _e.label = 3;
                    case 3:
                        _i++;
                        return [3 /*break*/, 1];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    Controller.prototype.evaluateTemplate = function (metadata, prop, defaultValue, req) {
        return __awaiter(this, void 0, void 0, function () {
            var meta, _a, _b;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        meta = metadata;
                        if (!meta.classParameters[prop]) return [3 /*break*/, 2];
                        if (!(meta.classParameters[prop] instanceof Function)) return [3 /*break*/, 2];
                        _a = meta.classParameters;
                        _b = prop;
                        return [4 /*yield*/, meta.classParameters[prop](req)];
                    case 1:
                        _a[_b] = _c.sent();
                        _c.label = 2;
                    case 2:
                        if (!meta.classParameters[prop]) {
                            meta.classParameters[prop] = defaultValue;
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    Controller.prototype.generateContextMetadata = function (metadata, req) {
        return __awaiter(this, void 0, void 0, function () {
            var meta, requests, _a, _b, _c;
            return __generator(this, function (_d) {
                switch (_d.label) {
                    case 0:
                        meta = __assign({}, metadata);
                        meta.classParameters = __assign({}, metadata.classParameters);
                        requests = [];
                        requests.push(this.evaluateTemplate(meta, 'listParentTemplate', _1.default.listParentTemplatePath, req));
                        requests.push(this.evaluateTemplate(meta, 'listTemplate', _1.default.listTemplatePath, req));
                        requests.push(this.evaluateTemplate(meta, 'editorParentTemplate', _1.default.editorParentTemplatePath, req));
                        requests.push(this.evaluateTemplate(meta, 'editorTemplate', _1.default.editorTemplatePath, req));
                        requests.push(this.evaluateTemplate(meta, 'popupEditorParentTemplate', _1.default.popupEditorParentTemplatePath, req));
                        requests.push(this.evaluateTemplate(meta, 'popupEditorTemplate', _1.default.popupEditorTemplatePath, req));
                        requests.push(this.evaluateTemplate(meta, 'batchDelete', null, req));
                        requests.push(this.evaluateTemplate(meta, 'disableCreation', null, req));
                        requests.push(this.evaluateTemplate(meta, 'disableDelete', null, req));
                        requests.push(this.evaluateTemplate(meta, 'defaultOrderBy', null, req));
                        requests.push(this.evaluateTemplate(meta, 'disableReloadOnList', null, req));
                        return [4 /*yield*/, Promise.all(requests)];
                    case 1:
                        _d.sent();
                        if (!(meta.classParameters.listActionTemplate &&
                            meta.classParameters.listActionTemplate instanceof Function)) return [3 /*break*/, 3];
                        _a = meta.classParameters;
                        return [4 /*yield*/, meta.classParameters.listActionTemplate(req)];
                    case 2:
                        _a.listActionTemplate = _d.sent();
                        _d.label = 3;
                    case 3:
                        if (!(meta.classParameters.listAdditionalActionTemplate &&
                            meta.classParameters.listAdditionalActionTemplate instanceof
                                Function)) return [3 /*break*/, 5];
                        _b = meta.classParameters;
                        return [4 /*yield*/, meta.classParameters.listAdditionalActionTemplate(req)];
                    case 4:
                        _b.listAdditionalActionTemplate = _d.sent();
                        _d.label = 5;
                    case 5:
                        if (!(meta.classParameters.listCustomDeleteAction &&
                            meta.classParameters.listCustomDeleteAction instanceof Function)) return [3 /*break*/, 7];
                        _c = meta.classParameters;
                        return [4 /*yield*/, meta.classParameters.listCustomDeleteAction(req)];
                    case 6:
                        _c.listCustomDeleteAction = _d.sent();
                        _d.label = 7;
                    case 7: return [2 /*return*/, meta];
                }
            });
        });
    };
    Controller.prototype.generateContextFields = function (metadata, req, entityData, forceReadOnly, forceHide) {
        if (forceReadOnly === void 0) { forceReadOnly = false; }
        if (forceHide === void 0) { forceHide = false; }
        return __awaiter(this, void 0, void 0, function () {
            var fields, key, _a, _b, _i, key, field, meta, _c, _d, updatedFields, currentEntity, evaluatedFields, f, f, _e, _f, _g, _h, _j;
            return __generator(this, function (_k) {
                switch (_k.label) {
                    case 0:
                        fields = {};
                        for (key in metadata.fields) {
                            fields[key] = metadata.fields[key];
                        }
                        _a = [];
                        for (_b in fields)
                            _a.push(_b);
                        _i = 0;
                        _k.label = 1;
                    case 1:
                        if (!(_i < _a.length)) return [3 /*break*/, 25];
                        key = _a[_i];
                        field = fields[key];
                        meta = this.retrieveMetadata(field.selfType);
                        if (!(forceReadOnly || field.readOnly instanceof Function)) return [3 /*break*/, 5];
                        fields[key] = __assign({}, field);
                        if (!forceReadOnly) return [3 /*break*/, 2];
                        fields[key].readOnly = true;
                        return [3 /*break*/, 4];
                    case 2:
                        _c = fields[key];
                        return [4 /*yield*/, field.readOnly(req, entityData)];
                    case 3:
                        _c.readOnly = _k.sent();
                        _k.label = 4;
                    case 4:
                        field = fields[key];
                        _k.label = 5;
                    case 5:
                        if (!(forceHide || field.hide instanceof Function)) return [3 /*break*/, 9];
                        fields[key] = __assign({}, field);
                        if (!forceHide) return [3 /*break*/, 6];
                        fields[key].hide = true;
                        return [3 /*break*/, 8];
                    case 6:
                        _d = fields[key];
                        return [4 /*yield*/, field.hide(req, entityData)];
                    case 7:
                        _d.hide = _k.sent();
                        _k.label = 8;
                    case 8:
                        field = fields[key];
                        _k.label = 9;
                    case 9:
                        if (!meta) return [3 /*break*/, 14];
                        if (!!field.query) return [3 /*break*/, 13];
                        fields[key] = __assign({}, field);
                        updatedFields = {};
                        if (!(field.type == decorators_1.AdminType.Expanded ||
                            field.type == decorators_1.AdminType.ExpandedAndSelection)) return [3 /*break*/, 11];
                        currentEntity = (entityData !== null && entityData !== void 0 ? entityData : {})[key];
                        return [4 /*yield*/, this.generateContextFields(meta, req, currentEntity, field.readOnly, field.hide)];
                    case 10:
                        evaluatedFields = _k.sent();
                        for (f in meta.fields) {
                            updatedFields[key + '-' + f] = evaluatedFields[f];
                        }
                        return [3 /*break*/, 12];
                    case 11:
                        for (f in meta.fields) {
                            updatedFields[key + '-' + f] = meta.fields[f];
                        }
                        _k.label = 12;
                    case 12:
                        meta = __assign(__assign({}, meta), { fields: updatedFields });
                        _k.label = 13;
                    case 13:
                        fields[key].metadata = meta;
                        field.metadata = meta;
                        _k.label = 14;
                    case 14:
                        if (!(field.required instanceof Function)) return [3 /*break*/, 16];
                        fields[key] = __assign({}, field);
                        _e = fields[key];
                        return [4 /*yield*/, field.required(req, entityData)];
                    case 15:
                        _e.required = _k.sent();
                        field = fields[key];
                        _k.label = 16;
                    case 16:
                        if (!(field.values instanceof Function)) return [3 /*break*/, 18];
                        fields[key] = __assign({}, field);
                        _f = fields[key];
                        return [4 /*yield*/, field.values(req, entityData)];
                    case 17:
                        _f.values = _k.sent();
                        field = fields[key];
                        _k.label = 18;
                    case 18:
                        if (!(field.defaultValue instanceof Function)) return [3 /*break*/, 20];
                        fields[key] = __assign({}, field);
                        _g = fields[key];
                        return [4 /*yield*/, field.defaultValue(req, entityData)];
                    case 19:
                        _g.defaultValue = _k.sent();
                        field = fields[key];
                        _k.label = 20;
                    case 20:
                        if (!(field.hundredsSeparator instanceof Function)) return [3 /*break*/, 22];
                        fields[key] = __assign({}, field);
                        _h = fields[key];
                        return [4 /*yield*/, field.hundredsSeparator(req, entityData)];
                    case 21:
                        _h.hundredsSeparator = _k.sent();
                        field = fields[key];
                        _k.label = 22;
                    case 22:
                        if (!(field.decimalSeparator instanceof Function)) return [3 /*break*/, 24];
                        fields[key] = __assign({}, field);
                        _j = fields[key];
                        return [4 /*yield*/, field.decimalSeparator(req, entityData)];
                    case 23:
                        _j.decimalSeparator = _k.sent();
                        field = fields[key];
                        _k.label = 24;
                    case 24:
                        _i++;
                        return [3 /*break*/, 1];
                    case 25: return [2 /*return*/, fields];
                }
            });
        });
    };
    Controller.prototype.getUrlWithoutPage = function (req) {
        return this.getUrlWithoutParameter(req, ['page']);
    };
    Controller.prototype.getUrlWithoutOrder = function (req) {
        return this.getUrlWithoutParameter(req, ['orderby']);
    };
    Controller.prototype.getUrlWithoutPageOrOrder = function (req) {
        return this.getUrlWithoutParameter(req, ['orderby', 'page']);
    };
    Controller.prototype.getUrlWithoutParameter = function (req, parameters) {
        var u = (req.baseUrl + req.path).replace(/\/$/, '') + '?';
        for (var key in req.query) {
            var found = false;
            for (var _i = 0, parameters_1 = parameters; _i < parameters_1.length; _i++) {
                var p = parameters_1[_i];
                if (key.toLowerCase() == p) {
                    found = true;
                    break;
                }
            }
            if (found) {
                continue;
            }
            u += this.generateQueryValue(key, req.query[key]);
        }
        return u;
    };
    Controller.prototype.generateQueryValue = function (key, q) {
        var m = key + '=';
        if (q instanceof Array) {
            m += q[0] + '&';
            for (var i = 1; i < q.length; i++) {
                m += key + '=' + q[i] + '&';
            }
            return m;
        }
        return m + q + '&';
    };
    return Controller;
}(base_controller_1.BaseController));
exports.Controller = Controller;
