import { __awaiter } from "tslib";
import { GraphDocument } from './../classes/';
import { GraphElement, GraphDatasource } from '@csnext/cs-data';
import Axios from 'axios';
import EntityEditor from '../components/entity-management/entity-editor.vue';
import { EntityParser } from "../plugins/EntityParser";
import { guidGenerator } from '@csnext/cs-core';
import { PropertyValueType } from '@csnext/cs-data';
import { CsMap } from '@csnext/cs-map';
import RelationEditor from "./../components/document-management/relation-editor.vue";
import { AppState } from '@csnext/cs-client';
import FeatureTypeEditor from "./../components/datamodel/feature-type-editor.vue";
import { EmptyDocumentImport } from '../plugins/empty-document-import';
import { GraphCrossFilter } from '../filters/graph-cross-filter';
export class DocDatasource extends GraphDatasource {
    constructor(base_url, timesourceId) {
        super();
        this.base_url = base_url;
        this.timesourceId = timesourceId;
        this.id = 'isrd';
        this.searchEntities = [];
        this.viewTypes = {};
        this.documentPlugins = [];
        this.importPlugins = [];
        this.viewerPlugins = [];
        this.visibleViewTypes = [];
        this.editor = null;
        this.filters = [];
        this.entityParser = new EntityParser();
        this.layers = {};
    }
    reset() {
        const _super = Object.create(null, {
            reset: { get: () => super.reset }
        });
        return __awaiter(this, void 0, void 0, function* () {
            yield _super.reset.call(this);
            this.activeDocument = undefined;
            this.activeElement = undefined;
            return Promise.resolve(true);
        });
    }
    getObservation(type) {
        if (this.featureTypes && this.featureTypes.hasOwnProperty(type)) {
            return Object.assign({}, this.featureTypes[type]);
        }
        else {
            return this.getObservation('node');
        }
    }
    initCrossFilter() {
        this.crossFilter = new GraphCrossFilter(this);
    }
    initLayer(ml, key, obs) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            let l = yield ml.addGeojsonLayer(obs.title, undefined, {
                popup: "{{properties.title}}",
                type: (['country', 'province'].includes(key)) ? 'fill' : 'circle',
                mapbox: {
                    fillPaint: {
                        "fill-color": "blue",
                        "fill-opacity": 0.3,
                        "fill-outline-color": 'black'
                    },
                    circlePaint: {
                        "circle-radius": 13,
                        "circle-color": "blue",
                        "circle-stroke-color": 'gray',
                        "circle-stroke-width": 1
                    }
                },
                pointCircle: true
            });
            this.layers[key] = l;
            l._source._featureType = obs;
            (_a = l._source) === null || _a === void 0 ? void 0 : _a.updateFeatureTypePropertyMap(l._source._featureType);
            l.style.popup = '${title}';
            l.openFeatureDetails = false;
            ml.hideLayer(l);
            this.busManager.subscribe(l._events, 'feature', (a, f) => {
                if (a === CsMap.FEATURE_SELECT) {
                    try {
                        let elementid = f.feature.properties.element;
                        let el = this.getElement(elementid);
                        if (el) {
                            this.openElement(el);
                        }
                    }
                    catch (e) {
                    }
                }
            });
            return l;
        });
    }
    openFeatureTypeEditor(featureType) {
        $cs.openRightSidebarWidget({
            component: FeatureTypeEditor,
            options: { showToolbar: false, title: featureType.title },
            datasource: 'isrd', data: { type: featureType }
        }, { open: true }, 'featuretype');
    }
    openOriginal(original) {
        var _a;
        if ((_a = original.properties) === null || _a === void 0 ? void 0 : _a.format) {
            alert('open original');
        }
    }
    initLayers(defaultLayer) {
        return __awaiter(this, void 0, void 0, function* () {
        });
    }
    addElementToLayer(layer, element) {
        if (layer && element.properties) {
            if (element.properties.hasOwnProperty('shape')) {
                let fc = JSON.parse(element.properties['shape']);
                if ((fc === null || fc === void 0 ? void 0 : fc.features) && fc.features.length > 0) {
                    let p = fc.features[0];
                    p.id = element.id;
                    p.properties = Object.assign(Object.assign({}, element.properties), {
                        title: GraphElement.getTitle(element),
                        element: element.id,
                        color: GraphElement.getBackgroundColor(element)
                    });
                    layer.features.push(p);
                }
            }
            else if (element.properties.hasOwnProperty('lat') && element.properties.hasOwnProperty('lon')) {
                let lat = parseFloat(element.properties['lat']);
                element.properties['lat'] = lat;
                let lon = parseFloat(element.properties['lon']);
                element.properties['lon'] = lon;
                layer.features.push({
                    "type": "Feature",
                    "id": element.id,
                    "properties": Object.assign(Object.assign({}, element.properties), {
                        title: GraphElement.getTitle(element),
                        element: element.id,
                        color: GraphElement.getBackgroundColor(element)
                    }),
                    "geometry": {
                        "type": "Point",
                        "coordinates": [lon, lat]
                    }
                });
            }
            else {
                layer.features.push({
                    "type": "Feature",
                    "id": element.id,
                    "properties": Object.assign(Object.assign({}, element.properties), {
                        title: GraphElement.getTitle(element),
                        element: element.id,
                        color: GraphElement.getBackgroundColor(element)
                    }),
                    "geometry": {
                        "type": "Point",
                        "coordinates": [0, 0]
                    }
                });
            }
        }
    }
    updateLayer(type, traversal = false) {
        var _a;
        if (this.graph && type.type && this.layers.hasOwnProperty(type.type)) {
            const elements = this.getClassElements(type.type, traversal);
            const layer = this.layers[type.type];
            if (elements && ((_a = layer._source) === null || _a === void 0 ? void 0 : _a._data) && elements.length > 0 && layer) {
                for (const el of elements) {
                    this.addElementToLayer(layer._source._data, el);
                }
                layer.updateLayer();
            }
        }
    }
    updateLayers() {
        var _a;
        if (this.graph) {
            for (const key in this.graph) {
                if (this.graph.hasOwnProperty(key)) {
                    const element = this.graph[key];
                    if (element.classId && this.layers.hasOwnProperty(element.classId)) {
                        let layer = (_a = this.layers[element.classId]._source) === null || _a === void 0 ? void 0 : _a._data;
                        if (layer) {
                            this.addElementToLayer(layer, element);
                        }
                    }
                }
                for (const key in this.layers) {
                    if (Object.prototype.hasOwnProperty.call(this.layers, key)) {
                        const layer = this.layers[key];
                        layer.updateLayer();
                    }
                }
            }
        }
    }
    updateLayerElements(elements) {
        return __awaiter(this, void 0, void 0, function* () {
        });
    }
    linkObservationToDocument(observation, doc) {
        return new Promise((resolve, reject) => {
            if (!observation._node || !doc) {
                reject();
                return;
            }
            this.addNewEdge({ fromId: doc.id, toId: observation._node.id, classId: 'CONTAINS_OBSERVATION' }).then((e) => __awaiter(this, void 0, void 0, function* () {
                observation._edge = e;
                e.to = observation._node;
                e.from = doc;
                yield this.addEdge(e);
                yield this.saveDocument(doc);
                resolve(observation);
            })).catch(() => {
                reject();
            });
        });
    }
    linkEntityToDocument(entity, doc) {
        return new Promise((resolve, reject) => {
            if (!entity._node || !doc) {
                reject();
                return;
            }
            this.addNewEdge({ fromId: doc.id, toId: entity._node.id, classId: 'CONTAINS' }, false).then((e) => __awaiter(this, void 0, void 0, function* () {
                entity._edge = e;
                e.to = entity._node;
                e.from = doc;
                yield this.addEdge(e);
                yield this.parseEntities();
                yield this.saveDocument(doc);
                resolve(entity);
            })).catch(() => {
                reject();
            });
        });
    }
    linkEntityListToDocument(entity, doc) {
        return new Promise((resolve, reject) => {
            if (!entity.node || !doc) {
                reject();
                return;
            }
            this.addNewEdge({ fromId: doc.id, toId: entity.node.id, classId: 'CONTAINS' }, false).then((e) => __awaiter(this, void 0, void 0, function* () {
                entity.edge = e;
                e.to = entity.node;
                e.from = doc;
                yield this.addEdge(e);
                yield this.saveDocument(doc);
                yield this.parseEntities();
                resolve(entity);
            })).catch(() => {
                reject();
            });
        });
    }
    triggerDocumentEntities() {
        this.bus.publish(DocDatasource.DOCUMENT_ENTITIES, DocDatasource.ENTITIES_UPDATED);
    }
    updateHighlights() {
        this.bus.publish(DocDatasource.DOCUMENT_ENTITIES, 'updateHighlights');
    }
    removeEntityNodeFromDocument(node, doc) {
        if (!this.editor) {
            return;
        }
    }
    setActiveUser(user) {
        if (!(user === null || user === void 0 ? void 0 : user.id)) {
            return;
        }
        this.activeUser = user;
        localStorage.setItem('active-user-id', user.id);
    }
    initUser() {
        return __awaiter(this, void 0, void 0, function* () {
            const users = this.getClassElements('user', true, { hasObjectProperties: [{ property: 'agent_type', operator: '==', value: 'person' }] });
            if (users.length === 0) {
                try {
                    const newUser = yield this.addNewNode({
                        classId: 'user',
                        properties: {
                            name: 'default',
                            agent_type: 'person'
                        }
                    });
                    this.setActiveUser(newUser);
                }
                catch (e) {
                    console.log('Error adding default user');
                }
            }
            else {
                const activeUserId = localStorage.getItem('active-user-id');
                if (activeUserId && this.graph.hasOwnProperty(activeUserId)) {
                    this.setActiveUser(this.graph[activeUserId]);
                }
                else {
                    this.setActiveUser(users[0]);
                }
            }
        });
    }
    removeEntityListFromDocument(list, doc, removeInstances = false) {
        return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
            var _a, _b, _c;
            for (const ent of list.instances) {
                ent._approved = false;
                if (ent._edge) {
                    delete ent._edge;
                }
                if (ent._docEntity) {
                    this.removeEntityNodeFromDocument(ent._docEntity, doc);
                }
            }
            if (removeInstances && ((_a = list.instances) === null || _a === void 0 ? void 0 : _a.length) > 0) {
                doc.entities = (_b = doc.entities) === null || _b === void 0 ? void 0 : _b.filter(t => !list.instances.includes(t));
            }
            if (list.edge && doc) {
                try {
                    yield this.removeEdge(list.edge);
                }
                catch (e) {
                    console.log(e);
                }
            }
            doc._outgoing = (_c = doc._outgoing) === null || _c === void 0 ? void 0 : _c.filter(r => { var _a; return r.toId !== ((_a = list.node) === null || _a === void 0 ? void 0 : _a.id); });
            list._approved = false;
            list.edge = undefined;
            yield this.parseEntities();
            this.updateEdges();
            yield this.saveDocument(doc);
            resolve(list);
        }));
    }
    removeEntityFromDocument(entity, doc) {
        return new Promise((resolve, reject) => {
            if (!entity._edge) {
                resolve(entity);
                return;
            }
            this.removeEdge(entity._edge).then(() => __awaiter(this, void 0, void 0, function* () {
                yield this.parseEntities();
                resolve(entity);
            })).catch((e) => {
                console.log(e);
                reject();
            });
        });
    }
    loadTypes() {
        return __awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => {
                const url = `${this.base_url}/types`;
                console.log('loading types');
                $cs.loader.addLoader('types', 'loading types');
                Axios.get(url).then(r => {
                    if (r.data) {
                        this.featureTypes = r.data;
                        $cs.loader.removeLoader('types');
                        resolve(true);
                    }
                    else {
                        $cs.loader.removeLoader('types');
                        reject();
                    }
                }).catch(e => {
                    console.log(e);
                    reject();
                    $cs.loader.removeLoader('types');
                });
            });
        });
    }
    elementEditorForm(node) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
        let form = {
            showToolbar: false,
            hideTitle: true,
            optionalSupport: true,
            isPanel: false,
            fields: []
        };
        if (node === null || node === void 0 ? void 0 : node._featureType) {
            const ft = node === null || node === void 0 ? void 0 : node._featureType;
            if (ft === null || ft === void 0 ? void 0 : ft.properties) {
                for (const pt of ft.properties) {
                    let required = pt.required;
                    let group = pt.group;
                    let section = pt.section;
                    switch (pt.type) {
                        case PropertyValueType.datetime:
                            (_a = form.fields) === null || _a === void 0 ? void 0 : _a.push({
                                title: pt.label,
                                _key: pt.key,
                                type: 'datetimepicker',
                                readonly: pt.readonly,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.string:
                            (_b = form.fields) === null || _b === void 0 ? void 0 : _b.push({
                                title: pt.label,
                                _key: pt.key,
                                type: 'string',
                                readonly: pt.readonly,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.image:
                            (_c = form.fields) === null || _c === void 0 ? void 0 : _c.push({
                                title: pt.label,
                                _key: pt.key,
                                type: 'string',
                                readonly: pt.readonly,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.element:
                            (_d = form.fields) === null || _d === void 0 ? void 0 : _d.push({
                                title: pt.label,
                                _key: pt.key,
                                type: 'combobox-objects',
                                keyText: 'properties.name',
                                keyValue: 'id',
                                options: (() => {
                                    if (pt.elementType) {
                                        return this.getClassElements(pt.elementType);
                                    }
                                    return [];
                                }),
                                readonly: pt.readonly,
                                clearable: !required,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.options:
                            (_e = form.fields) === null || _e === void 0 ? void 0 : _e.push({
                                title: pt.label,
                                _key: pt.key,
                                type: 'selection',
                                options: pt.options,
                                readonly: pt.readonly,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.wkt:
                            (_f = form.fields) === null || _f === void 0 ? void 0 : _f.push({
                                title: pt.label,
                                _key: pt.key,
                                type: 'string',
                                readonly: pt.readonly,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.boolean:
                            (_g = form.fields) === null || _g === void 0 ? void 0 : _g.push({
                                title: pt.label,
                                _key: pt.key,
                                type: 'checkbox',
                                readonly: pt.readonly,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.number:
                            let inputType = ((_h = pt.attributes) === null || _h === void 0 ? void 0 : _h.hasOwnProperty('form:type')) ? pt.attributes['form:type'] : "number";
                            (_j = form.fields) === null || _j === void 0 ? void 0 : _j.push({
                                title: pt.label,
                                _key: pt.key,
                                type: inputType,
                                min: pt.min,
                                max: pt.max,
                                readonly: pt.readonly,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.tags:
                            (_k = form.fields) === null || _k === void 0 ? void 0 : _k.push({
                                title: pt.label,
                                _key: pt.key,
                                type: 'chips',
                                readonly: pt.readonly,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.epoch:
                            (_l = form.fields) === null || _l === void 0 ? void 0 : _l.push({
                                title: pt.label,
                                _key: pt.key,
                                type: 'epochdatetimepicker',
                                readonly: pt.readonly,
                                required,
                                group,
                                section
                            });
                            break;
                        case PropertyValueType.relation:
                            (_m = form.fields) === null || _m === void 0 ? void 0 : _m.push({
                                title: pt.label,
                                _key: pt.key,
                                component: RelationEditor,
                                type: 'component',
                                data: {
                                    relation: pt.relation,
                                    node: node,
                                    graph: this
                                },
                                readonly: pt.readonly,
                                keyText: 'properties.name',
                                keyValue: 'id',
                                required: required || (node._outgoing && node._outgoing.findIndex(r => { var _a; return r.classId === ((_a = pt.relation) === null || _a === void 0 ? void 0 : _a.type); }) !== -1),
                                group,
                                section
                            });
                            break;
                    }
                }
            }
        }
        return form;
    }
    loadGraph(url, clearCache = false) {
        return __awaiter(this, void 0, void 0, function* () {
            let jsonGraph;
            const local = undefined;
            if (local && !clearCache) {
                jsonGraph = JSON.parse(local);
            }
            else {
                $cs.loader.addLoader('loadinggraph', 'loading graph', { color: 'green' });
                const query = yield Axios.get(url);
                if (query.data) {
                    jsonGraph = (query.data);
                    try {
                    }
                    catch (e) {
                    }
                }
                $cs.loader.removeLoader('loadinggraph');
            }
            if (jsonGraph) {
                let inputTypes;
                if (this._meta) {
                    inputTypes = Object.values(this._meta).filter(ft => ft._inheritedTypes && ft.type && ft._inheritedTypes.includes('input')).map(ft => ft.type);
                }
                for (const item of jsonGraph.filter(i => i.type === 'node')) {
                    if (item.properties && !item.properties.id && item.id) {
                        item.properties.id = item.id;
                    }
                    if (item.id && item.classId) {
                        const classId = item.classId;
                        if (inputTypes && inputTypes.includes(classId)) {
                            let el = Object.assign(Object.assign({}, new GraphDocument()), { id: item.id, classId: item.classId, title: item.properties.name, properties: item.properties, alternatives: item.alternatives });
                            this.initElement(el);
                            this.addNode(el);
                        }
                        else {
                            let el = Object.assign(Object.assign({}, new GraphElement()), { id: item.id, classId: item.classId, title: item.properties.name, properties: item.properties, alternatives: item.alternatives });
                            this.initElement(el);
                            this.addNode(el);
                        }
                    }
                }
                for (const item of jsonGraph.filter(i => i.type === 'edge')) {
                    if (item.properties && item.hasOwnProperty('fromId') && item.hasOwnProperty('toId')) {
                        yield this.addEdge({
                            id: item.id,
                            toId: item.toId,
                            fromId: item.fromId,
                            classId: item.classId,
                            properties: item.properties
                        });
                    }
                }
                ;
                this.updateNodes();
                this.updateEdges();
                this.updateFeatureTypeStats();
                this.initUser();
                this.parseDocuments();
            }
        });
    }
    deleteDocument(doc) {
        this.removeNode(doc, true).finally(() => {
            var _a;
            this.events.publish(DocDatasource.DOCUMENT, DocDatasource.DOCUMENT_UPDATED);
            if (((_a = this.activeDocument) === null || _a === void 0 ? void 0 : _a.id) === doc.id) {
                this.activateDocument(undefined);
            }
        });
    }
    openEntityEditor(entity) {
        $cs.openRightSidebarWidget({
            component: EntityEditor,
            data: {
                isrd: this,
                entity: entity
            }
        }, { open: true }, 'details');
    }
    addToOperation(operation, element) {
        this.addNewEdge({
            fromId: operation.id,
            toId: element.id,
            classId: 'PART_OF',
        })
            .then((e) => __awaiter(this, void 0, void 0, function* () {
            $cs.Translate('ADDED_TO_OPERATION');
        }))
            .catch(() => { });
    }
    parseDocument(doc) {
        return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
            var _a, _b, _c;
            if (this.documentPlugins) {
                for (const plugin of this.documentPlugins.filter(p => typeof p.callDocument === 'function')) {
                    try {
                        console.log(`Plugin: ${plugin.title}, Output: `);
                        if (((_a = doc.properties) === null || _a === void 0 ? void 0 : _a.text) && ((_b = doc.properties) === null || _b === void 0 ? void 0 : _b.text.length) > 0) {
                            let res = yield plugin.callDocument(doc, this);
                            if (!res.error && res.document) {
                                console.log((_c = doc.entities) === null || _c === void 0 ? void 0 : _c.filter(e => e._node));
                            }
                            else {
                                console.log(`Error: ${res.error}`);
                            }
                        }
                    }
                    catch (e) {
                        console.log(e);
                    }
                }
                this.linkDocumentEntities(doc);
                try {
                    yield this.entityParser.callDocument(doc, this);
                }
                catch (e) {
                    console.log('Error parsing entities');
                    console.log(e);
                    resolve(doc);
                }
            }
            resolve(doc);
        }));
    }
    addNewDocument(makeActive = false) {
        return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
        }));
    }
    addNewReport(type) {
        return new Promise(() => __awaiter(this, void 0, void 0, function* () {
        }));
    }
    initDocumentPlugins() {
        this.documentPlugins = [];
    }
    openViewer(element, document) {
        var _a;
        if (((_a = element.properties) === null || _a === void 0 ? void 0 : _a.format) && this.viewerPlugins) {
            const viewer = this.viewerPlugins.find((v) => { var _a; return v.formats && v.formats.includes((_a = element.properties) === null || _a === void 0 ? void 0 : _a.format); });
            if (viewer) {
                viewer.call(element, document, this);
            }
        }
    }
    linkDocumentObservations(doc) {
        if (!doc.observations || !doc.entities || !this._meta) {
            return;
        }
        for (const obs of doc.observations) {
            if (obs.type && this._meta && this._meta.hasOwnProperty(obs.type)) {
                obs._featureType = this._meta[obs.type];
            }
            if (!obs._featureType) {
                obs._featureType = Object.values(this._meta).find(f => f.title === obs.type);
            }
            if (obs._featureType) {
                if (obs.relations) {
                    for (const r of obs.relations) {
                        if (r.hasOwnProperty('entity_idx') && doc.entities) {
                            r._entity = doc.entities.find(e => e.entity_idx === r.entity_idx.toString());
                        }
                    }
                }
                if (obs.properties) {
                    for (const r of obs.properties) {
                        if (r.hasOwnProperty('entity_idx') && doc.entities) {
                            r._entity = doc.entities.find(e => e.entity_idx === r.entity_idx.toString());
                        }
                    }
                }
            }
        }
    }
    linkDocumentEntities(doc) {
        if (doc.entities && typeof Array.isArray(doc.entities)) {
            for (const e of doc.entities) {
                if (e.node_id && !e._node) {
                    e._node = this.getElement(e.node_id);
                    if (!e._node) {
                        delete e.node_id;
                    }
                }
            }
        }
    }
    initDocument(doc) {
        var _a, _b, _c, _d, _e;
        if (!doc.properties) {
            doc.properties = {};
        }
        if (!doc.properties.text) {
            doc.properties.text = '';
        }
        if ((_a = doc.properties) === null || _a === void 0 ? void 0 : _a.doc) {
            doc.doc = JSON.parse((_b = doc.properties) === null || _b === void 0 ? void 0 : _b.doc);
        }
        else {
            doc.doc = {
                type: "doc",
                content: []
            };
        }
        doc._source = (_c = doc._outgoing) === null || _c === void 0 ? void 0 : _c.find(e => e.classId === 'FROM_SOURCE');
        doc.sourceId = (_d = doc._source) === null || _d === void 0 ? void 0 : _d.id;
        if ((_e = doc.properties) === null || _e === void 0 ? void 0 : _e.notes) {
            doc.notes = JSON.parse(doc.properties.notes);
        }
        if (doc.properties.entities) {
            doc.entities = JSON.parse(doc.properties.entities);
            this.linkDocumentEntities(doc);
        }
        if (doc.properties.observations) {
            doc.observations = JSON.parse(doc.properties.observations);
            this.linkDocumentObservations(doc);
        }
        return doc;
    }
    parseDocuments() {
        if (!this.graph) {
            return;
        }
        const docs = this.getClassElements('input', true);
        if (docs) {
            for (const doc of docs) {
                this.initDocument(doc);
                this.updateDocumentOriginals(doc);
            }
        }
    }
    checkQueryParams() {
        var _a, _b, _c, _d;
        if (!((_b = (_a = $cs.router) === null || _a === void 0 ? void 0 : _a.currentRoute) === null || _b === void 0 ? void 0 : _b.query)) {
            return;
        }
        const q = (_d = (_c = $cs.router) === null || _c === void 0 ? void 0 : _c.currentRoute) === null || _d === void 0 ? void 0 : _d.query;
        if (q.hasOwnProperty('nodedetails')) {
            const node = this.getElement(q['nodedetails']);
            if (node) {
                this.openElement(node);
            }
        }
    }
    refresh(loadGraph = false) {
        return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
            if (!loadGraph) {
                this.updateNodes(true);
                this.updateEdges(true);
                resolve(true);
            }
            else {
                try {
                    yield this.reset();
                    this.initDocumentPlugins();
                    yield this.loadTypes();
                    this.mergeFeatureTypes();
                    try {
                        yield this.loadGraph(`${this.base_url}/graph/all`, loadGraph);
                        this.updateNodes(true);
                        this.updateEdges(true);
                        yield this.parseDocuments();
                        this.loadGraphPresets();
                        this.checkQueryParams();
                        console.log('publish graph loaded event');
                        this.bus.publish(GraphDatasource.GRAPH_EVENTS, GraphDatasource.GRAPH_LOADED);
                    }
                    catch (e) {
                        alert('error loading data');
                    }
                    resolve(true);
                }
                catch (e) {
                    reject();
                }
            }
        }));
    }
    saveFeatureType(type) {
        return new Promise((resolve, reject) => {
            if (this.featureTypes) {
                let res = {};
                for (const type of Object.keys(this.featureTypes)) {
                    let ft = this.featureTypes[type]._originalFeatureType;
                    if (ft) {
                        if (!ft.properties) {
                            ft.properties = [];
                        }
                        let f = JSON.parse(JSON.stringify(ft, (key, value) => {
                            if (value.properties) {
                                value.properties = value.properties.filter((t) => !t._originalType || t._originalType === value.type);
                            }
                            else {
                            }
                            if (key.startsWith('_')) {
                                return undefined;
                            }
                            if (key === "propertyMap") {
                                return undefined;
                            }
                            if (value.infoPanels) {
                                const newPanels = {};
                                Object.keys(value.infoPanels).forEach(key => {
                                    if (key && (value === null || value === void 0 ? void 0 : value.infoPanels) && value.infoPanels[key] && !value.infoPanels[key]._originalType) {
                                        newPanels[key] = value.infoPanels[key];
                                    }
                                });
                                value.infoPanels = newPanels;
                            }
                            return value;
                        }, 2));
                        res[type] = f;
                    }
                }
                ;
                let updateJSON = JSON.stringify(res, undefined, 2);
                $cs.loader.addLoader(`updatetypes`);
                Axios.post(`${this.base_url}/types`, JSON.parse(updateJSON)).then(() => {
                }).catch(e => {
                    reject(e);
                }).finally(() => {
                    $cs.loader.removeLoader(`updatetypes`);
                });
                this.mergeFeatureTypes();
            }
            resolve(type);
        });
    }
    getSimplifiedEntities(doc) {
        if (!doc.entities) {
            return [];
        }
        let entities = [];
        for (const ent of doc.entities) {
            let entity = Object.assign({}, ent);
            for (const key of Object.keys(entity)) {
                if (key.startsWith('_') && entity.hasOwnProperty(key)) {
                    delete entity[key];
                }
            }
            delete entity["@context"];
            entities.push(entity);
        }
        return entities;
    }
    getSimplifiedObservations(doc) {
        if (!doc.observations) {
            return [];
        }
        let observations = [];
        for (const obs of doc.observations) {
            let observation = Object.assign({}, obs);
            for (const key of Object.keys(observations)) {
                if (key.startsWith('_') && observation.hasOwnProperty(key)) {
                    delete observation[key];
                }
            }
            if (observation.relations) {
                for (const r of observation.relations) {
                    delete r._entity;
                }
            }
            if (observation.properties) {
                for (const p of observation.properties) {
                    delete p._entity;
                }
                delete observation["@context"];
                observations.push(observation);
            }
        }
        return observations;
    }
    saveDocument(d) {
        return new Promise((resolve, reject) => {
            let doc = Object.assign({}, d);
            if (!doc.properties) {
                doc.properties = {};
            }
            if (doc.id) {
                doc.properties.id = doc.id;
            }
            doc.properties.doc = JSON.stringify(doc.doc);
            doc.properties.sourceId = doc.sourceId;
            doc.properties.notes = doc.notes;
            doc.properties.credibility = doc.credibility;
            doc.properties.reliability = doc.reliability;
            if (doc.entities) {
                doc.properties.entities = JSON.stringify(this.getSimplifiedEntities(doc));
            }
            if (doc.notes) {
                doc.properties.notes = JSON.stringify(doc.notes);
            }
            delete doc.doc;
            if (doc.observations) {
                doc.properties.observations = JSON.stringify(this.getSimplifiedObservations(doc));
            }
            this.saveNode(doc).then(() => __awaiter(this, void 0, void 0, function* () {
                this.updateNodes(true);
                yield this.updateEdges(true);
                this.events.publish(DocDatasource.DOCUMENT, DocDatasource.DOCUMENT_UPDATED, d);
                resolve(d);
            })).catch((e) => {
                console.log(e);
                reject();
            });
        });
    }
    removeObservation(observation) {
        return new Promise(() => __awaiter(this, void 0, void 0, function* () {
            let element = observation._node;
            if (element === null || element === void 0 ? void 0 : element._outgoing) {
                for (const rel of element._outgoing) {
                    yield this.removeEdge(rel);
                }
            }
            if (element === null || element === void 0 ? void 0 : element._incomming) {
                for (const rel of element._incomming) {
                    yield this.removeEdge(rel);
                }
            }
            this.parseEntities();
        }));
    }
    updateTextEntity(document, entity) {
        if (!entity.text || entity.text.length === 0) {
            return;
        }
        if (!document.entities) {
            document.entities = [];
        }
        const indx = document.entities.findIndex(e => e.entity_idx === entity.entity_idx);
        if (indx === -1) {
            document.entities.push(entity);
        }
        else {
            document.entities[indx] = entity;
        }
    }
    updateDocumentOriginals(doc) {
        if (!doc._outgoing) {
            return;
        }
        GraphElement.updateOriginals(doc);
    }
    refreshViewTypes() {
        this.visibleViewTypes = Object.values(this.viewTypes).filter((vt) => vt._selected);
    }
    syncEntities(document, content, triggerUpdated = false, key) {
        if (!document || !content || !Array.isArray(content)) {
            return;
        }
        if (!key) {
            key = guidGenerator();
        }
        if (!document.entities) {
            document.entities = [];
        }
        for (const node of content) {
            if (node.attrs && node.type === 'text-entity') {
                if (!node.attrs.id) {
                    node.attrs.id = guidGenerator();
                }
                let e = document.entities.find(e => e.entity_idx === node.attrs.id);
                if (!e) {
                    e = {
                        text: node.attrs.text,
                        id: node.attrs.id,
                        entity_class: node.attrs.type,
                        _key: key
                    };
                    document.entities.push(e);
                }
                else {
                    e._key = key;
                }
                e._docEntity = node;
            }
            if (node.content) {
                this.syncEntities(document, node.content, false, key);
            }
        }
        if (triggerUpdated) {
            console.log('remove old entities');
            document.entities = document.entities.filter(e => e._key === key);
            this.triggerDocumentEntities();
        }
        this.refreshViewTypes();
    }
    removeNode(element, relations = false, notify = false) {
        return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
            if (element && element.id) {
                if (relations) {
                    if (element._incomming) {
                        for (const incomming of element._incomming) {
                            yield this.removeEdge(incomming);
                        }
                    }
                    if (element._outgoing) {
                        for (const outgoing of element._outgoing) {
                            yield this.removeEdge(outgoing);
                        }
                    }
                }
                $cs.loader.addLoader(`remove-${element.id}`);
                Axios.post(`${this.base_url}/graph/remove`, undefined, { params: { id: element.id } }).then(() => __awaiter(this, void 0, void 0, function* () {
                    if (element.id) {
                        yield this.removeNodeById(element.id, relations);
                    }
                    this.events.publish(GraphDatasource.GRAPH_EVENTS, GraphDatasource.ELEMENT_REMOVED, element);
                    resolve(true);
                })).catch(e => {
                    reject(e);
                }).finally(() => {
                    var _a;
                    $cs.loader.removeLoader(`remove-${element.id}`);
                    if (notify) {
                        $cs.triggerNotification({ title: 'Node removed', text: (_a = element.properties) === null || _a === void 0 ? void 0 : _a.name });
                    }
                });
            }
        }));
    }
    saveNode(element) {
        return new Promise((resolve, reject) => {
            var _a;
            $cs.loader.addLoader(`store-${element.id}`);
            let body = Object.assign({}, element);
            body.alternatives = (_a = body._alternatives) === null || _a === void 0 ? void 0 : _a.join(',');
            if (body.properties) {
                body = Object.assign(body, body.properties);
                delete body.properties;
            }
            for (const prop of Object.keys(body)) {
                if (prop.startsWith('_')) {
                    delete body[prop];
                }
            }
            delete body.class;
            this.updateNode(element, true);
            this.events.publish(GraphDatasource.GRAPH_EVENTS, GraphDatasource.ELEMENT_UPDATED, element);
            Axios.post(`${this.base_url}/graph/store`, body).then(() => {
                var _a;
                $cs.triggerNotification({ title: $cs.Translate('NODE_SAVED'), text: (_a = element.properties) === null || _a === void 0 ? void 0 : _a.name, timeout: 500, group: true });
                resolve(element);
            }).catch(e => {
                reject(e);
            }).finally(() => {
                $cs.loader.removeLoader(`store-${element.id}`);
            });
        });
    }
    parseEntities() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.activeDocument && this.entityParser) {
                try {
                    yield this.entityParser.callDocument(this.activeDocument, this);
                }
                catch (e) {
                }
            }
        });
    }
    activateDocument(doc) {
        return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
            this.activeDocument = doc;
            if (!doc) {
                reject();
            }
            else {
                $cs.data.activeDocument = doc === null || doc === void 0 ? void 0 : doc.id;
                if (doc.entities) {
                    yield this.entityParser.callDocument(doc, this);
                }
                this.bus.publish('document', 'activated', doc);
                resolve(doc);
            }
        }));
    }
    removeEdge(edge) {
        return new Promise((resolve) => {
            $cs.loader.addLoader(`unlink-${edge.id}`);
            Axios.post(`${this.base_url}/graph/unlinkId`, undefined, {
                params: {
                    id: edge.id
                }
            }).then((r) => __awaiter(this, void 0, void 0, function* () {
                var _a, _b, _c, _d;
                if ((_a = edge.from) === null || _a === void 0 ? void 0 : _a._outgoing) {
                    edge.from._outgoing = (_b = edge.from._outgoing) === null || _b === void 0 ? void 0 : _b.filter(e => e.id !== edge.id);
                }
                if ((_c = edge.to) === null || _c === void 0 ? void 0 : _c._incomming) {
                    edge.to._incomming = (_d = edge.to._incomming) === null || _d === void 0 ? void 0 : _d.filter(e => e.id !== edge.id);
                }
                if (edge.id && this.graph.hasOwnProperty(edge.id)) {
                    delete this.graph[edge.id];
                }
                this.events.publish(GraphDatasource.GRAPH_EVENTS, GraphDatasource.ELEMENT_REMOVED, edge);
                resolve(true);
            })).catch(() => {
                resolve(false);
            }).finally(() => {
                $cs.loader.removeLoader(`unlink-${edge.id}`);
            });
        });
    }
    addNewEdge(edge, updateEdges = true) {
        return new Promise((resolve, reject) => {
            edge = this.createEdge(edge);
            $cs.loader.addLoader(`store-${edge.id}`);
            Axios.post(`${this.base_url}/graph/link`, edge.properties, {
                params: {
                    fromId: edge.fromId,
                    toId: edge.toId,
                    classId: edge.classId
                }
            }).then((r) => __awaiter(this, void 0, void 0, function* () {
                yield this.addEdge(edge);
                if (updateEdges) {
                    yield this.updateEdges();
                    yield this.parseEntities();
                }
                this.events.publish(GraphDatasource.GRAPH_EVENTS, GraphDatasource.ELEMENT_ADDED, edge);
                resolve(edge);
            })).catch(e => {
                reject(e);
            }).finally(() => {
                $cs.loader.removeLoader(`store-${edge.id}`);
            });
        });
    }
    addNewNode(element) {
        return new Promise((resolve, reject) => {
            let res = this;
            if (!element.id) {
                element.id = element.classId + '-' + guidGenerator();
            }
            if (!element.properties) {
                element.properties = {};
            }
            if (!element.properties.name && element.id) {
                element.properties.name = element.id;
            }
            if (!element.properties.updated_time) {
                element.properties.updated_time = new Date().getTime();
            }
            if (!element.properties.created_time) {
                element.properties.created_time = new Date().getTime();
            }
            if (!element.properties.created_by && this.activeUser) {
                element.properties.created_by = this.activeUser.id;
            }
            if (!element.properties.updated_by && this.activeUser) {
                element.properties.updated_by = this.activeUser.id;
            }
            element.type = 'node';
            let body = Object.assign({}, element);
            console.log(body);
            if (body.properties) {
                body = Object.assign(body, body.properties);
                delete body.properties;
            }
            for (const prop of Object.keys(body)) {
                if (prop.startsWith('_')) {
                    body[prop] = undefined;
                }
            }
            $cs.loader.addLoader(`store-${element.id}`);
            Axios.post(`${this.base_url}/graph/store`, body).then(() => __awaiter(this, void 0, void 0, function* () {
                this.initElement(element);
                res = res.addElement(element);
                yield this.refresh();
                this.events.publish(GraphDatasource.GRAPH_EVENTS, GraphDatasource.ELEMENT_ADDED, element);
                resolve(element);
            })).catch(e => {
                reject(e);
            }).finally(() => {
                $cs.loader.removeLoader(`store-${element.id}`);
            });
        });
    }
    selectElementId(id, open = false) {
        const e = this.getElement(id);
        if (e) {
            this.selectElement(e, open);
            if (open) {
                this.openElement(e);
            }
        }
    }
    selectElement(element, open = false) {
        if (!element) {
            return;
        }
        element._collapsed = !element._collapsed;
        this.bus.publish('focus', 'element', element);
    }
    startEditElement(element) {
        element._isEditting = true;
        this.bus.publish('element', 'start-editing', element);
    }
    stopEditElement(element) {
        element._isEditting = false;
        this.bus.publish('element', 'stop-editing', element);
    }
    createKGView(elements, expand = false) {
        this.emptyGraph(false);
        if (elements) {
            for (const el of elements) {
                this.addElementToGraph(el, false);
            }
            this.triggerUpdateGraph();
        }
    }
    addElementToGraph(el, trigger = true) {
        var _a;
        if (((_a = this.activeGraphPreset) === null || _a === void 0 ? void 0 : _a._visibleNodes) && !this.activeGraphPreset._visibleNodes.includes(el)) {
            this.activeGraphPreset._visibleNodes.push(el);
            el._included = true;
            if (trigger) {
                this.triggerUpdateGraph(el);
                this.bus.publish(DocDatasource.PRESET_EVENTS, DocDatasource.PRESET_ELEMENT_ADDED, el);
            }
        }
    }
    removeElementFromGraph(el) {
        el._included = false;
        if (el._outgoing) {
            el._outgoing.map(e => e._included = false);
        }
        if (el._incomming) {
            el._incomming.map(e => e._included = false);
        }
        this.triggerUpdateGraph();
    }
    addRelationsToGraph(element, classId) {
        if (element === null || element === void 0 ? void 0 : element._outgoing) {
            for (const out of element === null || element === void 0 ? void 0 : element._outgoing) {
                if (out.to && (!classId || out.classId === classId)) {
                    this.addElementToGraph(out.to, false);
                }
            }
        }
        if (element === null || element === void 0 ? void 0 : element._incomming) {
            for (const incomming of element === null || element === void 0 ? void 0 : element._incomming) {
                if (incomming.from && (!classId || incomming.classId === classId)) {
                    this.addElementToGraph(incomming.from, false);
                }
            }
        }
        this.triggerUpdateGraph();
    }
    openElement(node) {
        if (typeof (node) === 'string') {
            const n = this.getElement(node);
            if (!n) {
                return;
            }
            else {
                node = n;
            }
        }
        if (!(node === null || node === void 0 ? void 0 : node.id)) {
            return;
        }
        this.activeElement = node;
        $cs.updateRouteQuery({ nodedetails: node.id });
        this.bus.publish('element', 'select-element', node);
        $cs.openRightSidebarKey('details');
        this.addElementToHistory(node.id);
    }
    updateSearchEntities() {
        var _a, _b, _c, _d;
        let entities = [];
        for (const node of Object.values(this.graph)) {
            let excludeClasses = ['instance', 'airport', 'document'];
            if (node.class && node.type === 'node' && !((_a = node.properties) === null || _a === void 0 ? void 0 : _a.nlp_ignore) && ((_b = node.properties) === null || _b === void 0 ? void 0 : _b.name) && !((_c = node.properties.name) === null || _c === void 0 ? void 0 : _c.startsWith('Q')) && !excludeClasses.includes(node.classId)) {
                entities.push(node);
                (_d = this.searchEntities) === null || _d === void 0 ? void 0 : _d.push({
                    id: node.id,
                    entity: node.properties.name,
                    ent_class: node.classId,
                    aka: node._alternatives
                });
            }
        }
        this.searchEntities = [...this.searchEntities, ...[]];
    }
    removeReports() {
        return __awaiter(this, void 0, void 0, function* () {
            let rec = this.getClassElements('aerial_reconnaissance');
            if (rec) {
                for (const r of rec) {
                    yield this.removeNode(r, true);
                }
            }
            let reports = this.getClassElements('airint_report');
            if (reports) {
                for (const report of reports) {
                    yield this.removeNode(report);
                }
            }
        });
    }
    setQueryParams() {
        var _a;
        if (!((_a = $cs.project.rightSidebar) === null || _a === void 0 ? void 0 : _a.open)) {
            $cs.removeRouteQueryParam('nodedetails');
        }
    }
    loadElementHistory() {
        const history = localStorage.getItem('element-history');
        if (history && history.length > 0) {
            this.elementHistory = history.split(',');
        }
        else {
            this.elementHistory = [];
        }
    }
    saveElementHistory() {
        if (!this.elementHistory) {
            return;
        }
        const history = this.elementHistory.join(',');
        localStorage.setItem('element-history', history);
    }
    addElementToHistory(id) {
        if (!this.elementHistory) {
            this.elementHistory = [];
        }
        else {
            this.elementHistory = this.elementHistory.filter(e => e !== id);
        }
        this.elementHistory.push(id);
        while (this.elementHistory.length > 10) {
            this.elementHistory.splice(0, 1);
        }
        this.saveElementHistory();
    }
    execute() {
        return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
            if (!this.graphPresets) {
                this.graphPresets = [];
            }
            yield this.refresh(true);
            this.loadElementHistory();
            this.importPlugins.push(new EmptyDocumentImport());
            if (this.timesourceId) {
                AppState.Instance.loadDatasource(this.timesourceId).then(ts => {
                    resolve(this);
                });
            }
            AppState.Instance.bus.subscribe(AppState.RIGHTSIDEBAR, (a, node) => {
                if (a === AppState.RIGHTSIDEBAR_CLOSED) {
                    this.setQueryParams();
                }
            });
            this.bus.subscribe(CsMap.NODE, (a, node) => {
                switch (a) {
                    case CsMap.NODE_SELECT:
                        this.openElement(node);
                        break;
                }
            });
            resolve(this);
        }));
    }
}
DocDatasource.DOCUMENT = 'document';
DocDatasource.DOCUMENT_UPDATED = 'document_updated';
DocDatasource.DOCUMENT_ENTITIES = 'document-entities';
DocDatasource.ENTITIES_UPDATED = 'entities-updated';
DocDatasource.FEATURE_TYPES = 'feature-types';
DocDatasource.FEATURE_TYPE_SELECTED = 'feature-type-selected';
//# sourceMappingURL=doc-datasource.js.map