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 __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import React, { useMemo, useCallback, useRef } from 'react';
import classnames from 'classnames';
import { identity, pipe, isEmpty } from 'ramda';
import { evaluateDeepEntityLabel, referencedEntityAttributeTypesSelectionStrategy, getEntityType, getReferencedEntityFromAttrValue, getReferencedRelationFromAttrValue, getReferencedEntityUri, getReferencedEntityTypeUri, getReferencedEntityTypeUriFromAttrType, getReferencedRelationAttrTypesUris, findAttributeTypeByUri, getCreatableAttributeTypes, createTemporaryEntity, convertReferencedEntityForAttrValue, createReferencedRelationForAttrValue, addReferencedRelationCrosswalks, getReferencedEntityUriFromAttrValue, checkCanEditAttribute, checkMetadataForCreate, isReltioCrosswalk, getErrorMessage, getErrorId, getReferencedEntityActiveError, isTempUri, getLabel, isAttributeTypeError, isAttributeHasMaskedValue } from '@reltio/mdm-sdk';
import { EditModeComplexAttribute } from '../EditModeComplexAttribute';
import { EntitySelector } from '../EntitySelector';
import { ErrorWrapper } from '../ErrorWrapper';
import { withContext } from '../HOCs/withContext';
import { useAttributeValueConfigPermissions } from '../contexts/ConfigPermissionsContext';
import { isHighlightedErrorType, ScrollToElementContext } from '../contexts/ScrollToElementContext';
import { useMdmAction, useMdmGlobalSearchRequestOptions, useMdmMetadata, useMdmModifiedEntity, useMdmShowMasking } from '../contexts/MdmModuleContext';
import { useScrollToAttributeError } from '../hooks/useScrollToAttributeError';
import { AddressAutoCompleteProvider } from '../contexts/AutoCompleteContext';
import { useStyles } from './styles';
var ReferenceAttributeEditor = function (props) {
    var _a;
    var styles = useStyles();
    var highlightedError = props.highlightedError, ownProps = __rest(props, ["highlightedError"]);
    var attributeValue = ownProps.attributeValue, attributeType = ownProps.attributeType, mode = ownProps.mode, crosswalks = ownProps.crosswalks, errors = ownProps.errors, onChangeAttribute = ownProps.onChangeAttribute;
    var initialAttributeValue = useRef(attributeValue);
    var _b = useScrollToAttributeError({ highlightedError: highlightedError, isSimple: true }), ref = _b.ref, errorClassName = _b.errorClassName;
    var entityUri = getReferencedEntityUriFromAttrValue(attributeValue);
    var entityDeleted = useMdmAction('entityDeleted');
    var entityCreated = useMdmAction('entityCreated');
    var errorDeactivated = useMdmAction('errorDeactivated');
    var mdmModifiedEntity = useMdmModifiedEntity(entityUri);
    var modifiedEntity = isTempUri(entityUri) ? mdmModifiedEntity : null;
    var metadata = useMdmMetadata();
    var globalSearchRequestOptions = useMdmGlobalSearchRequestOptions(['ovOnly']);
    var showMasking = useMdmShowMasking();
    var referencedEntity = getReferencedEntityFromAttrValue(attributeValue);
    var referencedRelation = getReferencedRelationFromAttrValue(attributeValue);
    var referencedEntityTypeUri = getReferencedEntityTypeUriFromAttrType(attributeType);
    var referencedEntityType = getEntityType(metadata, referencedEntityTypeUri);
    var label = modifiedEntity
        ? evaluateDeepEntityLabel(modifiedEntity, referencedEntityType.dataLabelPattern)
        : attributeValue.label;
    var entityTypesUris = useMemo(function () { return [referencedEntityTypeUri]; }, [referencedEntityTypeUri]);
    var allCrosswalks = useMemo(function () { return addReferencedRelationCrosswalks(crosswalks, referencedRelation); }, [crosswalks, referencedRelation]);
    var referencedEntityMissedError = useMemo(function () { return getReferencedEntityActiveError(attributeValue, errors); }, [attributeValue, errors]);
    var selectedEntity = useMemo(function () {
        return referencedEntity && {
            entityUri: getReferencedEntityUri(referencedEntity),
            entityType: getReferencedEntityTypeUri(referencedEntity),
            entityLabel: attributeValue.label
        };
    }, [referencedEntity, attributeValue.label]);
    var editableAttrTypes = useMemo(function () {
        return getReferencedRelationAttrTypesUris(attributeType)
            .map(function (attrTypeUri) { return findAttributeTypeByUri(metadata, attrTypeUri); })
            .filter(identity);
    }, [attributeType, metadata]);
    var newEntityAttrTypesSelectionStrategy = useCallback(function (entityType) { return referencedEntityAttributeTypesSelectionStrategy(attributeType, entityType); }, [attributeType]);
    var onChangeEntity = useCallback(function (entity) {
        if (modifiedEntity) {
            entityDeleted(modifiedEntity.uri);
        }
        var initialAttrValue = initialAttributeValue.current;
        var isInitialEntity = !isEmpty(entity) && entity.uri === getReferencedEntityUriFromAttrValue(initialAttrValue);
        var modifiedValue = __assign(__assign({}, attributeValue), { label: entity.label, refEntity: isInitialEntity ? initialAttrValue.refEntity : convertReferencedEntityForAttrValue(entity), refRelation: isInitialEntity
                ? initialAttrValue.refRelation
                : createReferencedRelationForAttrValue(attributeValue) });
        onChangeAttribute({ value: modifiedValue, attributeType: attributeType, uri: attributeValue.uri });
        if (referencedEntityMissedError) {
            errorDeactivated(getErrorId(referencedEntityMissedError));
        }
    }, [
        attributeValue,
        attributeType,
        modifiedEntity,
        onChangeAttribute,
        entityDeleted,
        errorDeactivated,
        referencedEntityMissedError
    ]);
    var onCreateEntity = useCallback(function (entityTypeUri, initValue) {
        var newEntityAttrTypes = pipe(newEntityAttrTypesSelectionStrategy, getCreatableAttributeTypes(mode))(referencedEntityType);
        var newEntity = createTemporaryEntity({
            entityTypeUri: entityTypeUri,
            initValue: initValue,
            attributeTypes: newEntityAttrTypes,
            metadata: metadata,
            mode: mode
        });
        onChangeEntity(newEntity);
        entityCreated(newEntity);
    }, [newEntityAttrTypesSelectionStrategy, mode, referencedEntityType, metadata, onChangeEntity, entityCreated]);
    var _c = useAttributeValueConfigPermissions(attributeValue.uri), configCanCreate = _c.canCreate, configCanUpdate = _c.canUpdate;
    var canChangeReferencedEntity = useMemo(function () {
        return configCanUpdate &&
            checkCanEditAttribute({
                attributeType: attributeType,
                attributeValue: attributeValue,
                mode: mode,
                isReltioCrosswalk: isReltioCrosswalk(crosswalks, attributeValue)
            });
    }, [attributeType, attributeValue, mode, crosswalks, configCanUpdate]);
    var canCreateReferencedEntity = useMemo(function () { return configCanCreate && checkMetadataForCreate(mode, referencedEntityType); }, [mode, referencedEntityType, configCanCreate]);
    var errorMessage = getErrorMessage(referencedEntityMissedError);
    var isMasked = showMasking && isAttributeHasMaskedValue(attributeValue);
    return (React.createElement(EditModeComplexAttribute, __assign({}, ownProps, { label: getLabel(label), attributeTypesList: editableAttrTypes, crosswalks: allCrosswalks, metadata: metadata }),
        React.createElement("div", { ref: ref, className: errorClassName },
            React.createElement(ErrorWrapper, { errorMessage: errorMessage },
                React.createElement(AddressAutoCompleteProvider, { entityUri: entityUri },
                    React.createElement(EntitySelector, { className: classnames(styles.item, (_a = {},
                            _a[styles.dense] = errorMessage || (selectedEntity && isTempUri(selectedEntity.entityUri)),
                            _a)), entity: selectedEntity || {}, entityTypesUris: entityTypesUris, globalSearchRequestOptions: globalSearchRequestOptions, mode: mode, isDisabled: !canChangeReferencedEntity || !!attributeValue.masked, onChange: onChangeEntity, onCreate: canCreateReferencedEntity ? onCreateEntity : undefined, metadata: metadata, attributeTypesSelectionStrategy: newEntityAttrTypesSelectionStrategy, isMasked: isMasked }))))));
};
export default withContext(ScrollToElementContext, function (contextValue, _a) {
    var attributeValue = _a.attributeValue, attributeType = _a.attributeType;
    var _b = contextValue || {}, element = _b.element, type = _b.type;
    var isHighlighted = isHighlightedErrorType(type) &&
        isAttributeTypeError(element, attributeValue.uri, attributeType.uri);
    return { highlightedError: isHighlighted ? contextValue : null };
}, ReferenceAttributeEditor);
