"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 __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 = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [0, 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 });
var storage_1 = require("../../util/storage");
var util_1 = require("../../util/util");
var base_api_1 = require("../../base/base-api");
var drupal_api_1 = require("./drupal-api");
var config_service_1 = require("../../config/config-service");
var Drupal = /** @class */ (function () {
    function Drupal(config, apiService) {
        if (config === void 0) { config = undefined; }
        if (apiService === void 0) { apiService = undefined; }
        this.user = {};
        this.saveLocalModel = storage_1.Storage.saveLocalModel;
        this.restoreLocalModel = storage_1.Storage.restoreLocalModel;
        this.cache = false;
        this.model = {
            // jsonApi
            entities: {},
            collections: {},
            nodes: {},
            views: {},
            menus: {},
            books: {},
            siteParams: {}
        };
        this.routes = {};
        this.version = 'drupal-8';
        this.sites = {};
        this.defaultUser = 'services';
        this.defaultAuthHeader = 'Basic c2VydmljZXM6OSs0djJGdm0zMi84Ymtl';
        this.config = config_service_1.ConfigService.instance;
        this.api = new base_api_1.BaseApi(); // todo: deprecate
        this.api.corsMode = 'cors'; // no-cors, cors, *same-origin (default)
        this.jsonApi = new drupal_api_1.DrupalApi();
        this.jsonApi.corsMode = 'cors';
        if (apiService) {
            // add Angular Observable api
            this.api = apiService;
        }
        this.model.entities = this.jsonApi.entities;
        this.model.collections = this.jsonApi.collections;
        this.model.nodes = this.jsonApi.nodes;
        this.model.views = this.jsonApi.views;
        if (config) {
            this.config.add(config);
        }
    }
    Drupal.prototype.init = function (options) {
        this.options = options;
        if (options.version) {
            this.version = options.version;
        }
        this.domain = options.domain;
        this.static = options.static || false;
        this.cache = options.cache || false;
        this.standalone = options.standalone || false;
        this.base_path = options.base_path || '/';
        this.protocol = options.protocol || 'http:';
        this.sites[this.domain] = {};
        this.file_directory_path = options.file_directory_path || 'sites/default/files';
        this.file_directory_path = this.baseUrl + this.file_directory_path;
        this.initApi(options);
        var promises = [];
        if (util_1.Util.isOnline() && !this.static) {
            // online
            // promises.push(jDrupal.connect());
            promises.push(this.getParams());
            promises.push(this.getLocalStorageCredentials());
            promises.push(this.jsonApi.getResourcesIndex(options.api.path_prefix, this.config.get('language')));
            promises.push(new Promise(function (resolve) {
                resolve();
            }));
            return Promise.all(promises);
        }
        else {
            // fixme: todo: offline or static
            // const self = this;
            return new Promise(function (resolve) {
                // self.restoreLocalModel(self.domain)
                // self.getLocalStorageCredentials().then(() => {
                resolve();
                // })
            });
        }
    };
    Drupal.prototype.initApi = function (options) {
        this.baseUrl = options.api.host = this.protocol + '//' + this.domain + this.base_path;
        this.api.init(options.api);
        this.jsonApi.init(options.api);
        this.jsonApi.cache = this.cache;
        // todo:
        if (this.config.get('drupal')['hasLanguages'] && this.config.get('language')) {
            //     this.api.baseUrl += this.config.getVar('language') + '/';
            //     this.jsonApi.baseUrl += this.config.getVar('language') + '/';
        }
        if (window) {
            // drupal-7
            if (window['Drupal']) {
                if (window['Drupal'].url && window['Drupal'].url.isLocal()) {
                    this.isLocal = true;
                }
                else {
                    this.isLocal = false;
                }
            }
            window['Drupal'] = window['Drupal'] || {};
            window['Drupal'].app_server_model = this.model;
            window['Drupal'].settings = window['Drupal'].settings || {};
            window['Drupal'].settings.baseUrl = this.baseUrl;
            // drupal-8
            window['drupalSettings'] = window['drupalSettings'] || {};
        }
        if (this.version === 'drupal-8') {
            if (window && !window['jDrupal']) {
                console.error('ERROR: jDrupal is not defined in the global namespace.');
                return;
            }
            this.jDrupal = jDrupal;
            jDrupal.config('sitePath', this.options.protocol + '//' + this.options.domain);
        }
        if ('withCredentials' in new XMLHttpRequest) {
            this.cors = true;
        }
    };
    ;
    Drupal.prototype.login = function (username, password) {
        var self = this;
        return new Promise(function (resolve) {
            jDrupal.userLogin(username, password).then(function () {
                self.user = jDrupal.currentUser();
                self.api.setCredentials(jDrupal.settings, 'drupal:authUser:' + self.domain);
                self.authenticated = true;
                resolve();
            });
        });
    };
    Drupal.prototype.logout = function () {
        var self = this;
        return new Promise(function (resolve) {
            // fixme: drupal permission denied;
            //jDrupal.userLogout().then(function() {
            self.jsonApi.logout('drupal:authUser:' + self.domain);
            self.authenticated = false;
            console.log('logged out');
            resolve();
        });
    };
    Drupal.prototype.getParams = function () {
        var self = this;
        return new Promise(function (resolve) {
            var url = 'index.php/rest/params';
            if (self.version === 'drupal-7') {
                url = '?q=rest/app_params.json';
            }
            self.jsonApi.get(url, { _format: 'json' }).then(function (result) {
                self.model.siteParams = self.siteParams = result;
                resolve(result);
            });
        });
    };
    ;
    // todo: get by name
    Drupal.prototype.getView = function (viewEntity, params) {
        var _this = this;
        if (params === void 0) { params = undefined; }
        return new Promise(function (resolve, reject) {
            var entity = viewEntity;
            _this.api.get(entity.attributes.display.rest_export_1.display_options.path, params).then(function (res) {
                _this.model.views[entity.attributes.id] = res;
                resolve();
            });
        });
    };
    Drupal.prototype.getAppNode = function (uuid) {
        var _this = this;
        return new Promise(function (resolve) {
            _this.jsonApi.getNode(uuid, 'app').then(function (node) {
                var dataPromises = [];
                var attributes = node.data.attributes;
                if (attributes.field_cache === true) {
                    _this.jsonApi.cache = attributes.field_cache;
                }
                // fixme: all collections
                if (attributes.field_preload_collections) {
                    dataPromises.push(_this.jsonApi.getAllCollections(true));
                }
                // getVar entity reference fields
                Object.keys(_this.model.entities).forEach(function (k) {
                    var entity = _this.model.entities[k];
                    if (entity.type == 'menu--menu') {
                        dataPromises.push(_this.menuLoad(entity.attributes.id, attributes.cache));
                    }
                    if (entity.type == 'view--view') {
                        dataPromises.push(_this.getView(entity));
                    }
                    if (entity.data && entity.data.type.match('node--')) {
                        if (entity.data.attributes.uuid !== uuid) {
                            dataPromises.push(_this.jsonApi.getNode(entity.data.attributes.uuid));
                        }
                    }
                });
                _this.getSiteData(dataPromises).then(function () {
                    resolve();
                });
            });
        });
    };
    Drupal.prototype.getSiteData = function (promises) {
        var self = this;
        return new Promise(function (resolve) {
            Promise.all(promises).then(function () {
                if (self.cache) {
                    self.saveLocalModel(self.model, self.domain);
                }
                resolve();
            });
        });
    };
    Drupal.prototype.getLocalStorageCredentials = function () {
        var self = this;
        return new Promise(function (resolve, reject) {
            var credentials = self.api.getCredentials('drupal:authUser:' + self.domain);
            if (credentials) {
                for (var k in credentials) {
                    jDrupal.settings[k] = credentials[k];
                }
                var auth = atob(credentials.auth_hash);
                self.login(auth.split(':')[0], auth.split(':')[1]).then(function () {
                    resolve();
                });
            }
            else {
                resolve();
            }
        });
    };
    Drupal.prototype.menuLoad = function (mid, preloadNodes) {
        if (preloadNodes === void 0) { preloadNodes = false; }
        return __awaiter(this, void 0, void 0, function () {
            var self;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        self = this;
                        return [4 /*yield*/, new Promise(function (resolve, reject) {
                                self.api.get('entity/menu/' + mid + '/tree', { _format: 'hal_json' }).then(function (res) {
                                    var menu = res;
                                    self.model.menus[mid] = menu;
                                    if (preloadNodes) {
                                        var nids_1 = [];
                                        menu.forEach(function (item) {
                                            if (item.link.route_parameters.node) {
                                                nids_1.push(item.link.route_parameters.node);
                                            }
                                        });
                                        self.jsonApi.getNodes(nids_1).then(function () {
                                            resolve(menu);
                                        });
                                    }
                                    else {
                                        resolve(menu);
                                    }
                                });
                            })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    Drupal.prototype.bookLoad = function (bid, preload) {
        if (preload === void 0) { preload = false; }
        var self = this;
        return new Promise(function (resolve, reject) {
            self.api.get('rest/book_tree/' + bid, { _format: 'hal_json' }).then(function (res) {
                self.model.books[bid] = res;
                var nids = self.parseBookTree(bid);
                if (preload) {
                    self.jsonApi.getNodes(nids).then(function () {
                        resolve(res);
                    });
                }
                else {
                    resolve(res);
                }
            });
        });
    };
    Drupal.prototype.parseBookTree = function (bid) {
        var data = this.model.books[bid];
        var below, items, nids, k, kk;
        items = [];
        nids = [];
        for (k in data) {
            below = data[k].below;
        }
        for (k in below) {
            var item = void 0;
            for (kk in below[k]) {
                item = below[k];
                item.link.route_parameters = { node: below[k].link.nid };
                item.link.href = '/node/' + item.link.nid;
                nids.push(below[k].link.nid);
            }
            items.push(item);
        }
        this.model.menus['book_' + bid] = items;
        return nids;
    };
    // todo: remove: deprecated
    Drupal.prototype.nodeLoad = function (nid) {
        var self = this;
        return new Promise(function (resolve, reject) {
            if (self.cache && self.model.nodes[nid]) {
                resolve(self.model.nodes[nid]);
            }
            else {
                jDrupal.nodeLoad(nid).then(function (node) {
                    self.model.nodes[node.entity.nid[0].value] = node;
                    self.model.entities[node.entity.uuid[0].value] = node.entity;
                    resolve(node);
                });
            }
        });
    };
    // todo: remove: deprecated
    Drupal.prototype.nodesLoad = function (nids) {
        var self = this;
        var promises = [];
        return new Promise(function (resolve) {
            for (var k in nids) {
                promises.push(self.nodeLoad(nids[k]));
            }
            Promise.all(promises).then(function () {
                resolve();
            });
        });
    };
    // todo: remove: deprecated
    Drupal.prototype.createNode = function (data) {
        var node = {};
        for (var key in data) {
            node[key] = [{ value: data[key] }];
        }
        node.title = [{ value: data.title }];
        node.type = [{ target_id: data.type }];
        node._links = {
            type: {
                href: jDrupal.restPath() + 'rest/type/node/' + data.type
            }
        };
        // if(data.type==='iframe'){
        //     field_iframe: [ { target_id: data.type } ]
        // }
        return new jDrupal.Node(node);
    };
    return Drupal;
}());
exports.Drupal = Drupal;
//# sourceMappingURL=drupal.js.map