var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
import { useCallback, useEffect, useRef, useState } from 'react';
import { difference, dissoc, evolve, isNil, pipe, without, identity } from 'ramda';
import { addNewAttribute, areOneHierarchyUris, createNewAttribute, editAttribute, findAttributeValueByUri, findAttributeValues, getAttributeValue, getCrosswalkAttributes, getRelationCrosswalks, isTempUri, removeAttribute } from '@reltio/mdm-sdk';
import { useAttributeActions } from './useAttributeActions';
var emptyArray = [];
export var useModifiedEntity = function (_a) {
    var entity = _a.entity, _b = _a.onLoad, onLoad = _b === void 0 ? identity : _b, _c = _a.onModify, onModify = _c === void 0 ? identity : _c, _d = _a.onError, onError = _d === void 0 ? identity : _d;
    var _e = useState(null), modifiedEntity = _e[0], setModifiedEntity = _e[1];
    var _f = useState([]), emptyTempAttributeUris = _f[0], setEmptyTempAttributeUris = _f[1];
    var _g = useState(null), crosswalksMap = _g[0], setCrosswalksMap = _g[1];
    var temporaryAttributes = useRef([]);
    var crosswalkForNewAttributes = useRef(null);
    var resetCrosswalkForNewAttributes = useCallback(function () {
        crosswalkForNewAttributes.current = null;
    }, []);
    var _h = useState(emptyArray), newlyCreatedAttributes = _h[0], setNewlyCreatedAttributes = _h[1];
    var groupCrosswalksByAttrUri = function (crosswalks) {
        if (crosswalks === void 0) { crosswalks = []; }
        return crosswalks.reduce(function (acc, crosswalk) {
            getCrosswalkAttributes(crosswalk).forEach(function (uri) {
                acc[uri] = __spreadArray(__spreadArray([], (acc[uri] || []), true), [crosswalk], false);
            });
            return acc;
        }, {});
    };
    useEffect(function () {
        var newCrosswalksMap = {
            entity: groupCrosswalksByAttrUri(entity === null || entity === void 0 ? void 0 : entity.crosswalks),
            relation: pipe(getRelationCrosswalks, groupCrosswalksByAttrUri)(entity)
        };
        if ((modifiedEntity === null || modifiedEntity === void 0 ? void 0 : modifiedEntity.uri) === (entity === null || entity === void 0 ? void 0 : entity.uri) && crosswalkForNewAttributes.current) {
            var ownerType = crosswalkForNewAttributes.current.ownerType;
            var newAttributes = Object.keys(newCrosswalksMap[ownerType]);
            var oldAttributes = Object.keys(crosswalksMap[ownerType]);
            setNewlyCreatedAttributes(difference(newAttributes, oldAttributes));
            setEmptyTempAttributeUris([]);
        }
        else {
            setNewlyCreatedAttributes(emptyArray);
        }
        resetCrosswalkForNewAttributes();
        setModifiedEntity(entity);
        setCrosswalksMap(newCrosswalksMap);
        temporaryAttributes.current = [];
    }, [entity]);
    var handleError = useCallback(pipe(onError, resetCrosswalkForNewAttributes), [
        onError,
        resetCrosswalkForNewAttributes
    ]);
    var _j = useAttributeActions({
        onLoad: onLoad,
        onSuccess: onModify,
        onError: handleError
    }), deleteAttribute = _j.deleteAttribute, ignoreAttribute = _j.ignoreAttribute, pinAttribute = _j.pinAttribute, createAttribute = _j.createAttribute, updateAttribute = _j.updateAttribute;
    var onAddAttribute = useCallback(function (_a) {
        var attributeType = _a.attributeType, parentUri = _a.parentUri, crosswalk = _a.crosswalk, index = _a.index;
        var newAttribute = createNewAttribute({ parentUri: parentUri, attributeType: attributeType });
        var uri = newAttribute.uri;
        if (crosswalk) {
            var ownerType_1 = crosswalk.ownerType;
            setCrosswalksMap(function (crosswalksMap) {
                var _a, _b;
                return (__assign(__assign({}, crosswalksMap), (_a = {}, _a[ownerType_1] = __assign(__assign({}, crosswalksMap[ownerType_1]), (_b = {}, _b[uri] = [crosswalk], _b)), _a)));
            });
        }
        if (!temporaryAttributes.current.some(function (tempUri) { return areOneHierarchyUris(uri, tempUri); })) {
            temporaryAttributes.current.push(uri);
        }
        if (!emptyTempAttributeUris.includes(newAttribute.uri)) {
            setEmptyTempAttributeUris(function (emptyTempAttributeUris) { return __spreadArray(__spreadArray([], emptyTempAttributeUris, true), [newAttribute.uri], false); });
        }
        setModifiedEntity(function (entity) {
            var _a;
            var targetIndex = isNil(index)
                ? (_a = findAttributeValues(entity, parentUri, attributeType.name)) === null || _a === void 0 ? void 0 : _a.length
                : index;
            return addNewAttribute({ entity: entity, attributeType: attributeType, newAttribute: newAttribute, index: targetIndex });
        });
    }, []);
    var onDeleteAttribute = useCallback(function (event) {
        var uri = event.attributeValue.uri, attributeType = event.attributeType;
        if (isTempUri(uri)) {
            setModifiedEntity(function (entity) { return removeAttribute({ entity: entity, attributeType: attributeType, uri: uri }); });
            setCrosswalksMap(evolve({
                entity: dissoc(uri),
                relation: dissoc(uri)
            }));
            temporaryAttributes.current = without([uri], temporaryAttributes.current);
        }
        else {
            deleteAttribute(event);
        }
    }, [deleteAttribute]);
    var onEditAttribute = useCallback(function (event) {
        if (isTempUri(event.attributeValue.uri)) {
            var attributeValue = event.attributeValue, attributeType = event.attributeType, crosswalk = event.crosswalk;
            if (!isNil(attributeValue.value)) {
                var uri_1 = attributeValue.uri;
                var tempAttributeUri = temporaryAttributes.current.find(function (tempUri) {
                    return areOneHierarchyUris(uri_1, tempUri);
                });
                var editedEntity = editAttribute({
                    entity: modifiedEntity,
                    attributeType: attributeType,
                    uri: uri_1,
                    value: getAttributeValue(attributeValue)
                });
                createAttribute({
                    attributeValue: findAttributeValueByUri(editedEntity, tempAttributeUri),
                    crosswalk: crosswalk
                });
                crosswalkForNewAttributes.current = crosswalk;
            }
        }
        else {
            updateAttribute(event);
        }
    }, [createAttribute, updateAttribute, modifiedEntity]);
    return {
        modifiedEntity: modifiedEntity,
        crosswalksMap: crosswalksMap,
        onAddAttribute: onAddAttribute,
        onDeleteAttribute: onDeleteAttribute,
        onPinAttribute: pinAttribute,
        onIgnoreAttribute: ignoreAttribute,
        onEditAttribute: onEditAttribute,
        newlyCreatedAttributes: newlyCreatedAttributes,
        emptyTempAttributeUris: emptyTempAttributeUris
    };
};
