"use strict";
var __extends = (this && this.__extends) || (function () {
    var 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 function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
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 api_1 = require("../../api");
var util_1 = require("../../util/util");
var JsonApi = /** @class */ (function (_super) {
    __extends(JsonApi, _super);
    function JsonApi() {
        var _this = _super.call(this) || this;
        _this.entities = {};
        _this.collections = {};
        _this.nodes = {};
        _this.resources = {};
        _this.views = {};
        _this.cache = false;
        _this.headers = {
            'Accept': 'application/vnd.api+json',
            'Content-Type': 'application/vnd.api+json'
        };
        return _this;
    }
    JsonApi.prototype.post = function (path, object) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        this.headers['Authorization'] = 'Basic ' + jDrupal.settings.auth_hash;
                        this.headers['X-CSRF-Token'] = jDrupal.settings.user_csrf_token;
                        this.headers['Content-Type'] = 'application/vnd.api+json';
                        return [4 /*yield*/, fetch("" + this.baseUrl + path, {
                                headers: this.headers,
                                method: 'POST',
                                body: JSON.stringify(object)
                            })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    JsonApi.prototype.patch = function (path, id, object) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        this.headers['Authorization'] = 'Basic ' + jDrupal.settings.auth_hash;
                        this.headers['X-CSRF-Token'] = jDrupal.settings.user_csrf_token;
                        this.headers['Content-Type'] = 'application/vnd.api+json';
                        if (object.data.attributes.changed) {
                            object.data.attributes.changed = undefined;
                        }
                        return [4 /*yield*/, fetch("" + this.baseUrl + path + "/" + id, {
                                headers: this.headers,
                                method: 'PATCH',
                                body: JSON.stringify(object)
                            })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // FIXME: causes php server error on drupal content admin page
    JsonApi.prototype.delete = function (path, id) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                this.headers['Authorization'] = 'Basic ' + jDrupal.settings.auth_hash;
                this.headers['X-CSRF-Token'] = jDrupal.settings.user_csrf_token;
                this.headers['Content-Type'] = 'application/vnd.api+json';
                return [2 /*return*/];
            });
        });
    };
    JsonApi.prototype.getResourcesIndex = function (jsonapi_endpoint, language) {
        if (jsonapi_endpoint === void 0) { jsonapi_endpoint = 'jsonapi'; }
        if (language === void 0) { language = undefined; }
        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) {
                                var url = self.baseUrl + 'index.php/';
                                if (language) {
                                    url += language + '/';
                                }
                                url += jsonapi_endpoint;
                                fetch(url)
                                    .then(function (response) {
                                    if (response.status >= 400) {
                                        throw new Error('JsonApi: Bad resources response from server');
                                    }
                                    return response.json();
                                })
                                    .then(function (result) {
                                    self.resources = result;
                                    self.baseUrl = result.links.self + '/';
                                    Object.keys(result.links).forEach(function (k, i) {
                                        if (k.match('node--')
                                            || k.match('menu--')
                                            || k.match('comment--')
                                            || k.match('file--')
                                            || k.match('taxonomy_term--')
                                            || k.match('node_type--')) {
                                            self.collections[k] = {};
                                        }
                                    });
                                    resolve(result);
                                });
                            })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    ;
    JsonApi.prototype.getCollection = function (collectionId, params, getRelationships) {
        if (params === void 0) { params = undefined; }
        if (getRelationships === void 0) { getRelationships = false; }
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            var path, collection, _a, _b, relatedPromises_1, _c, _d, _i, k;
            return __generator(this, function (_e) {
                switch (_e.label) {
                    case 0:
                        path = collectionId.split('--')[0] + '/' + collectionId.split('--')[1];
                        _a = this.collections;
                        _b = collectionId;
                        return [4 /*yield*/, this.get(path, {})];
                    case 1:
                        collection = _a[_b] = _e.sent();
                        if (!getRelationships) return [3 /*break*/, 5];
                        relatedPromises_1 = [];
                        Object.keys(collection.data).forEach(function (k) {
                            relatedPromises_1.push(_this.getEntityRelationships({ data: collection.data[k] }));
                        });
                        _c = [];
                        for (_d in relatedPromises_1)
                            _c.push(_d);
                        _i = 0;
                        _e.label = 2;
                    case 2:
                        if (!(_i < _c.length)) return [3 /*break*/, 5];
                        k = _c[_i];
                        return [4 /*yield*/, relatedPromises_1[k]];
                    case 3:
                        _e.sent();
                        _e.label = 4;
                    case 4:
                        _i++;
                        return [3 /*break*/, 2];
                    case 5:
                        Object.keys(collection.data).forEach(function (k, i) {
                            _this.entities[collection.data[k].attributes.uuid] = collection.data[k];
                        });
                        return [2 /*return*/, collection];
                }
            });
        });
    };
    JsonApi.prototype.getCollections = function (collectionIds, params, getRelationships) {
        if (params === void 0) { params = undefined; }
        if (getRelationships === void 0) { getRelationships = false; }
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            var promises, _a, _b, _i, k;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        promises = [];
                        collectionIds.forEach(function (id) {
                            promises.push(_this.getCollection(id, params, getRelationships));
                        });
                        _a = [];
                        for (_b in promises)
                            _a.push(_b);
                        _i = 0;
                        _c.label = 1;
                    case 1:
                        if (!(_i < _a.length)) return [3 /*break*/, 4];
                        k = _a[_i];
                        return [4 /*yield*/, promises[k]];
                    case 2:
                        _c.sent();
                        _c.label = 3;
                    case 3:
                        _i++;
                        return [3 /*break*/, 1];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    JsonApi.prototype.getAllCollections = function (getRelationships, exclude) {
        if (getRelationships === void 0) { getRelationships = false; }
        if (exclude === void 0) { exclude = []; }
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            var promises, _a, _b, _i, k;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        promises = [];
                        Object.keys(this.collections).forEach(function (k, i) {
                            var excluded = false;
                            exclude.forEach(function (id) {
                                if (id === k) {
                                    excluded = true;
                                }
                            });
                            if (!excluded) {
                                promises.push(_this.getCollection(k, {}, getRelationships));
                            }
                        });
                        _a = [];
                        for (_b in promises)
                            _a.push(_b);
                        _i = 0;
                        _c.label = 1;
                    case 1:
                        if (!(_i < _a.length)) return [3 /*break*/, 4];
                        k = _a[_i];
                        return [4 /*yield*/, promises[k]];
                    case 2:
                        _c.sent();
                        _c.label = 3;
                    case 3:
                        _i++;
                        return [3 /*break*/, 1];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    JsonApi.prototype.getResource = function (url, params) {
        if (params === void 0) { params = undefined; }
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            var resource;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (params) {
                            url += '?';
                            Object.keys(params).forEach(function (key) { return url += key + '=' + params[key] + '&'; });
                        }
                        return [4 /*yield*/, fetch(url, { headers: this.headers })
                                .then(function (response) {
                                if (response.status >= 400) {
                                    throw new Error('Bad response from server');
                                }
                                return response.json();
                            })
                                .then(function (data) {
                                // set entity + get relationships
                                if (data.data && data.data.id) {
                                    _this.entities[data.data.id] = data;
                                }
                                // set entities array + get relationships
                                if (data.data && Array.isArray(data.data)) {
                                    data.data.forEach(function (item) {
                                        if (item.id) {
                                            _this.entities[item.id] = item;
                                        }
                                    });
                                }
                                return data;
                            })];
                    case 1:
                        resource = _a.sent();
                        return [2 /*return*/, resource];
                }
            });
        });
    };
    JsonApi.prototype.getResources = function (urls) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            var promises, _a, _b, _i, k;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        promises = [];
                        urls.forEach(function (url) {
                            promises.push(_this.getResource(url));
                        });
                        _a = [];
                        for (_b in promises)
                            _a.push(_b);
                        _i = 0;
                        _c.label = 1;
                    case 1:
                        if (!(_i < _a.length)) return [3 /*break*/, 4];
                        k = _a[_i];
                        return [4 /*yield*/, promises[k]];
                    case 2:
                        _c.sent();
                        _c.label = 3;
                    case 3:
                        _i++;
                        return [3 /*break*/, 1];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    // todo:
    JsonApi.prototype.getEntityRelationships = function (entity) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, new Promise(function (resolve) {
                            var relationships = [];
                            if (entity.data && entity.data.relationships) {
                                Object.keys(entity.data.relationships).forEach(function (k, i) {
                                    // todo: nodes only: check other entity relation types
                                    if (k.match('field_')) {
                                        relationships.push(entity.data.relationships[k]);
                                    }
                                });
                            }
                            if (relationships.length) {
                                var urls_1 = [];
                                relationships.forEach(function (relationship) {
                                    if (relationship.links && relationship.links.self) {
                                        urls_1.push(relationship.links.related);
                                    }
                                });
                                if (urls_1.length) {
                                    _this.getResources(urls_1).then(function () {
                                        // console.log(urls);
                                        resolve();
                                    });
                                }
                                else {
                                    resolve();
                                }
                            }
                            else {
                                resolve();
                            }
                        })];
                    case 1: 
                    // console.log(entity);
                    return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    JsonApi.prototype.getNode = function (id, type) {
        if (type === void 0) { type = undefined; }
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            var self, idField;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        self = this;
                        id = util_1.Util.castToType(id);
                        idField = 'uuid';
                        if (typeof id === 'number') {
                            idField = 'nid';
                        }
                        return [4 /*yield*/, new Promise(function (resolve) {
                                var path;
                                // cached node
                                if (_this.cache) {
                                    var cachedNode_1;
                                    Object.keys(_this.entities).forEach(function (k) {
                                        if (_this.entities[k].data && _this.entities[k].data.attributes[idField] == id) {
                                            cachedNode_1 = _this.entities[k];
                                        }
                                    });
                                    if (cachedNode_1) {
                                        resolve(cachedNode_1);
                                        return;
                                    }
                                }
                                // define type from node_index view
                                if (_this.views['node_index']) {
                                    _this.views['node_index'].forEach(function (item) {
                                        if (item[idField] == id) {
                                            type = item.type;
                                        }
                                    });
                                }
                                if (type) {
                                    path = 'node/' + type;
                                    _this.get(path + '?filter[' + idField + '][value]=' + id).then(function (res) {
                                        parseNodeResult(res);
                                    });
                                }
                                else {
                                    // search through all node collections
                                    var nodeTypes_1 = [];
                                    Object.keys(_this.collections).forEach(function (k) {
                                        if (k.match('node--')) {
                                            nodeTypes_1.push(k);
                                        }
                                    });
                                    nodeTypes_1.forEach(function (type) {
                                        var path = type.split('--')[0] + '/' + type.split('--')[1];
                                        // fixme: stop further http requests after node match response
                                        _this.get(path + '?filter[' + idField + '][value]=' + id).then(function (res) {
                                            parseNodeResult(res);
                                        });
                                    });
                                }
                                function parseNodeResult(res) {
                                    if (res.data.length) {
                                        var node_1 = { data: res.data[0] };
                                        self.entities[res.data[0].id] = node_1;
                                        if (!self.collections[res.data[0].type].data) {
                                            self.collections[res.data[0].type].data = [];
                                        }
                                        // fixme: todo: check for doubles before push
                                        self.collections[res.data[0].type].data.push(node_1);
                                        // todo: deprecate, use collections + entities only
                                        self.nodes[res.data[0].attributes.nid] = node_1;
                                        // get relationships
                                        if (node_1.data.relationships) {
                                            self.getEntityRelationships(node_1).then(function () {
                                                resolve(node_1);
                                            });
                                        }
                                    }
                                }
                            })];
                    case 1: return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    JsonApi.prototype.getNodes = function (ids) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            var promises, _a, _b, _i, k;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        promises = [];
                        ids.forEach(function (id) {
                            promises.push(_this.getNode(id));
                        });
                        _a = [];
                        for (_b in promises)
                            _a.push(_b);
                        _i = 0;
                        _c.label = 1;
                    case 1:
                        if (!(_i < _a.length)) return [3 /*break*/, 4];
                        k = _a[_i];
                        return [4 /*yield*/, promises[k]];
                    case 2:
                        _c.sent();
                        _c.label = 3;
                    case 3:
                        _i++;
                        return [3 /*break*/, 1];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    JsonApi.prototype.saveNode = function (node) {
        return __awaiter(this, void 0, void 0, function () {
            var path;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        path = node.data.type.split('--')[0] + '/' + node.data.type.split('--')[1];
                        if (!!node.data.id) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.post(path, node)];
                    case 1:
                        _a.sent();
                        return [3 /*break*/, 4];
                    case 2: return [4 /*yield*/, this.patch(path, node.data.id, node)];
                    case 3:
                        _a.sent();
                        _a.label = 4;
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    JsonApi.prototype.deleteNode = function (node) {
        return __awaiter(this, void 0, void 0, function () {
            var path;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        path = node.data.type.split('--')[0] + '/' + node.data.type.split('--')[1];
                        return [4 /*yield*/, this.delete(path, node.data.id).then(function (arg) {
                                // fixme: todo: delete from collections + entities
                                // if (this.entities[node.data.id]){
                                //     this.entities[node.data.id] = undefined;
                                // }
                                // let collection = this.collections[node.data.type];
                                // if(collection.data && collection.data.length) {
                                //     collection.data.forEach((collectionNode,i) => {
                                //         if(node.data.id === collectionNode.data.id){
                                //             // collection.data.slice(i)
                                //         }
                                //     });
                                // }
                            })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // todo: check
    JsonApi.prototype.getById = function (entity_id) {
        var _this = this;
        var entity;
        Object.keys(this.collections).forEach(function (k, i) {
            if (_this.collections[k]['data'] && _this.collections[k]['data'].length) {
                _this.collections[k]['data'].forEach(function (entityObject) {
                    if (entityObject.id === entity_id) {
                        entity = entityObject;
                    }
                });
            }
        });
        if (entity) {
            return { data: entity };
        }
        // return entity;
    };
    JsonApi.prototype.getByNodeId = function (nid) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            var entity;
            return __generator(this, function (_a) {
                Object.keys(this.collections).forEach(function (k, i) {
                    if (k.match('node--') && _this.collections[k]['data'] && _this.collections[k]['data'].length) {
                        _this.collections[k]['data'].forEach(function (entityObject) {
                            if (entityObject.attributes.nid == nid) {
                                entity = entityObject;
                            }
                        });
                    }
                });
                if (entity) {
                    return [2 /*return*/, { data: entity }];
                }
                else {
                }
                return [2 /*return*/];
            });
        });
    };
    // public async entityLoad(entity_type_id: string, bundle_id: string, entity_id: any) {
    //     if(entity_type_id === 'node'){
    //         // if( typeof entity_id === 'number'){  }
    //     }
    //     // return await this.get(entity_type_id+'/'+bundle_id+'/'+entity_id);
    //     console.log(entity_type_id+'/'+bundle_id+'/'+entity_id);
    // }
    JsonApi.prototype.getByNid = function (nid, type) {
        if (type === void 0) { type = undefined; }
    };
    return JsonApi;
}(api_1.Api));
exports.JsonApi = JsonApi;
//# sourceMappingURL=json-api.js.map