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);
};
import { clone, has, isNil } from 'ramda';
import { DCROperationTypes, DCRTypes, isRelationTypeUri, MetadataPermissions, checkMetadataPermission, isRoleAttrType, isTagAttrType, checkSubAttributesPermissions } from '@reltio/mdm-sdk';
export var isEditableChange = function (change, entityInfo) {
    var _a;
    var currentAttributeTypeUri = (_a = change.attributeType) === null || _a === void 0 ? void 0 : _a.uri;
    var isExistingReferenceEntityChange = entityInfo.isExist &&
        currentAttributeTypeUri &&
        change.isReferenceSubAttribute &&
        change.operation === DCROperationTypes.ADDED &&
        !isRelationTypeUri(currentAttributeTypeUri);
    return !!currentAttributeTypeUri && !isExistingReferenceEntityChange && !isNil(change.newValue);
};
var isPrimitiveValue = function (value) {
    return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
};
var addLineIdRecursively = function (value, basePath) {
    if (value == null)
        return value;
    if (Array.isArray(value)) {
        return value.map(function (entry, index) {
            if (entry && typeof entry === 'object') {
                var entryPath = "".concat(basePath, "/").concat(index);
                var newEntry = clone(entry);
                newEntry.lineIds = [entryPath];
                var v = newEntry.value;
                if (typeof v === 'object' && v !== null) {
                    newEntry.value = addLineIdRecursively(v, "".concat(entryPath, "/value"));
                }
                return newEntry;
            }
            return entry;
        });
    }
    if (typeof value === 'object') {
        var result = {};
        for (var _i = 0, _a = Object.entries(value); _i < _a.length; _i++) {
            var _b = _a[_i], key = _b[0], val = _b[1];
            var childPath = "".concat(basePath, "/").concat(key);
            result[key] = addLineIdRecursively(val, childPath);
        }
        return result;
    }
    return value;
};
var addLineIdToChangeValue = function (container, basePath, type) {
    if (container == null)
        return container;
    if ([DCRTypes.CREATE_ENTITY, DCRTypes.CREATE_RELATIONSHIP].includes(type)) {
        var attributes = void 0;
        if ('attributes' in container && typeof container.attributes === 'object') {
            attributes = addLineIdRecursively(container.attributes, "".concat(basePath, "/attributes"));
        }
        return __assign(__assign({}, container), { attributes: attributes, lineIds: [basePath] });
    }
    if (Array.isArray(container)) {
        return { value: container, lineIds: [basePath] };
    }
    if (typeof container === 'object' && 'value' in container) {
        var containerValue = container.value;
        return __assign(__assign({}, container), { lineIds: [basePath], value: isPrimitiveValue(containerValue)
                ? containerValue
                : addLineIdRecursively(containerValue, "".concat(basePath, "/value")) });
    }
    return container;
};
export var addLineIdToValue = function (data) {
    var enrichedData = clone(data);
    for (var entityOrRelationKey in enrichedData) {
        var entityOrRelationId = entityOrRelationKey.split('/')[1];
        var changeList = enrichedData[entityOrRelationKey];
        if (!Array.isArray(changeList))
            continue;
        for (var _i = 0, changeList_1 = changeList; _i < changeList_1.length; _i++) {
            var change = changeList_1[_i];
            var changeId = change.id;
            var type = change.type;
            if (change.newValue != null) {
                var root = "".concat(entityOrRelationId, "/").concat(changeId, "/newValue");
                change.newValue = addLineIdToChangeValue(change.newValue, root, type);
            }
            if (change.oldValue != null) {
                var root = "".concat(entityOrRelationId, "/").concat(changeId, "/oldValue");
                change.oldValue = addLineIdToChangeValue(change.oldValue, root, type);
            }
            change.lineIds = ["".concat(entityOrRelationId, "/").concat(changeId)];
        }
    }
    return enrichedData;
};
export var isDiffChange = function (change) {
    return has('level', change);
};
export var checkCanInitiateChangeRequest = function (metadata, entityType, change) {
    if (change.relationType) {
        return checkCanInitChangeRequestForRelation(metadata, change.attributeValue, change.relationType);
    }
    if (isRoleAttrType(change.attributeType) || isTagAttrType(change.attributeType)) {
        return checkCanInitChangeRequestForSpecialAttribute(entityType);
    }
    return checkCanInitChangeRequestForAttribute(metadata, change.attributeValue, change.attributeType);
};
var checkCanInitChangeRequestForSpecialAttribute = function (entityType) {
    return checkMetadataPermission(MetadataPermissions.INITIATE_CHANGE_REQUEST, entityType);
};
var checkCanInitChangeRequestForAttribute = function (metadata, attributeValue, attributeType) {
    var _a;
    var preparedAttributeValue = typeof (attributeValue === null || attributeValue === void 0 ? void 0 : attributeValue.value) === 'object' && 'newValue' in attributeValue.value
        ? (_a = attributeValue === null || attributeValue === void 0 ? void 0 : attributeValue.value) === null || _a === void 0 ? void 0 : _a.newValue
        : attributeValue;
    return (checkMetadataPermission(MetadataPermissions.INITIATE_CHANGE_REQUEST, attributeType) &&
        checkSubAttributesPermissions(MetadataPermissions.INITIATE_CHANGE_REQUEST, metadata, preparedAttributeValue, attributeType));
};
var checkCanInitChangeRequestForRelation = function (metadata, attributeValue, relationType) {
    var preparedAttributeValue = Object.entries(attributeValue)
        .filter(function (_a) {
        var key = _a[0];
        return relationType.attributes.some(function (attr) { return attr.name === key; });
    })
        .reduce(function (acc, _a) {
        var key = _a[0], value = _a[1];
        acc[key] = value;
        return acc;
    }, {});
    return (checkMetadataPermission(MetadataPermissions.INITIATE_CHANGE_REQUEST, relationType) &&
        Object.keys(preparedAttributeValue).every(function (attributeValueKey) {
            var attributeType = relationType.attributes.find(function (attribute) { return attribute.name === attributeValueKey; });
            return (checkMetadataPermission(MetadataPermissions.INITIATE_CHANGE_REQUEST, attributeType) &&
                checkSubAttributesPermissions(MetadataPermissions.INITIATE_CHANGE_REQUEST, metadata, preparedAttributeValue[attributeValueKey], attributeType));
        }));
};
