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());
    });
};
import { Storage } from '../../util/storage';
import { Util } from '../../util/util';
import { BaseApi } from '../../base/base-api';
import { DrupalApi } from './drupal-api';
import { ConfigService } from '../../config/config-service';
export class Drupal {
    constructor(config = undefined, apiService = undefined) {
        this.user = {};
        this.saveLocalModel = Storage.saveLocalModel;
        this.restoreLocalModel = 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 = ConfigService.instance;
        this.api = new BaseApi(); // todo: deprecate
        this.api.corsMode = 'cors'; // no-cors, cors, *same-origin (default)
        this.jsonApi = new 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);
        }
    }
    init(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);
        let promises = [];
        if (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();
                // })
            });
        }
    }
    initApi(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;
        }
    }
    ;
    login(username, password) {
        const 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();
            });
        });
    }
    logout() {
        const 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();
        });
    }
    getParams() {
        const self = this;
        return new Promise(function (resolve) {
            let url = 'index.php/rest/params';
            if (self.version === 'drupal-7') {
                url = '?q=rest/app_params.json';
            }
            self.jsonApi.get(url, { _format: 'json' }).then((result) => {
                self.model.siteParams = self.siteParams = result;
                resolve(result);
            });
        });
    }
    ;
    // todo: get by name
    getView(viewEntity, params = undefined) {
        return new Promise((resolve, reject) => {
            let entity = viewEntity;
            this.api.get(entity.attributes.display.rest_export_1.display_options.path, params).then((res) => {
                this.model.views[entity.attributes.id] = res;
                resolve();
            });
        });
    }
    getAppNode(uuid) {
        return new Promise((resolve) => {
            this.jsonApi.getNode(uuid, 'app').then((node) => {
                let dataPromises = [];
                let 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((k) => {
                    let 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(() => {
                    resolve();
                });
            });
        });
    }
    getSiteData(promises) {
        const self = this;
        return new Promise(function (resolve) {
            Promise.all(promises).then(function () {
                if (self.cache) {
                    self.saveLocalModel(self.model, self.domain);
                }
                resolve();
            });
        });
    }
    getLocalStorageCredentials() {
        const self = this;
        return new Promise(function (resolve, reject) {
            const credentials = self.api.getCredentials('drupal:authUser:' + self.domain);
            if (credentials) {
                for (const k in credentials) {
                    jDrupal.settings[k] = credentials[k];
                }
                const auth = atob(credentials.auth_hash);
                self.login(auth.split(':')[0], auth.split(':')[1]).then(() => {
                    resolve();
                });
            }
            else {
                resolve();
            }
        });
    }
    menuLoad(mid, preloadNodes = false) {
        return __awaiter(this, void 0, void 0, function* () {
            const self = this;
            yield new Promise(function (resolve, reject) {
                self.api.get('entity/menu/' + mid + '/tree', { _format: 'hal_json' }).then((res) => {
                    const menu = res;
                    self.model.menus[mid] = menu;
                    if (preloadNodes) {
                        const nids = [];
                        menu.forEach((item) => {
                            if (item.link.route_parameters.node) {
                                nids.push(item.link.route_parameters.node);
                            }
                        });
                        self.jsonApi.getNodes(nids).then(() => {
                            resolve(menu);
                        });
                    }
                    else {
                        resolve(menu);
                    }
                });
            });
        });
    }
    bookLoad(bid, preload = false) {
        const self = this;
        return new Promise(function (resolve, reject) {
            self.api.get('rest/book_tree/' + bid, { _format: 'hal_json' }).then((res) => {
                self.model.books[bid] = res;
                const nids = self.parseBookTree(bid);
                if (preload) {
                    self.jsonApi.getNodes(nids).then(() => {
                        resolve(res);
                    });
                }
                else {
                    resolve(res);
                }
            });
        });
    }
    parseBookTree(bid) {
        const data = this.model.books[bid];
        let below, items, nids, k, kk;
        items = [];
        nids = [];
        for (k in data) {
            below = data[k].below;
        }
        for (k in below) {
            let item;
            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
    nodeLoad(nid) {
        const 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
    nodesLoad(nids) {
        const self = this;
        const promises = [];
        return new Promise(function (resolve) {
            for (const k in nids) {
                promises.push(self.nodeLoad(nids[k]));
            }
            Promise.all(promises).then(function () {
                resolve();
            });
        });
    }
    // todo: remove: deprecated
    createNode(data) {
        let node = {};
        for (const 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);
    }
}
//# sourceMappingURL=drupal.js.map