/**
 * Copyright (c) 2020-present, Goldman Sachs
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { addUniqueEntry, assertTrue, deleteEntry, guaranteeType, swapEntry, } from '@finos/legend-shared';
import { action } from 'mobx';
import { GenericType, Class, observe_Enum, observe_DerivedProperty, observe_GenericTypeReference, observe_Property, observe_RawVariableExpression, observe_Stereotype, observe_StereotypeReference, observe_Tag, observe_TaggedValue, observe_Constraint, observe_GenericType, observe_Unit, observe_RawLambda, isStubbed_PackageableElement, getOtherAssociatedProperty, observe_EmbeddedData, observe_FunctionTestSuite, observe_FunctionParameterValue, } from '@finos/legend-graph';
// --------------------------------------------- Packageable Element -------------------------------------
export const packageableElementReference_setValue = action((ref, value) => {
    ref.value = value;
});
// --------------------------------------------- Class -------------------------------------
export const class_deleteProperty = action((_class, val) => {
    deleteEntry(_class.properties, val);
});
export const class_addProperty = action((_class, val) => {
    addUniqueEntry(_class.properties, observe_Property(val));
});
export const class_swapProperties = action((_class, sourceProperty, targetProperty) => {
    swapEntry(_class.properties, sourceProperty, targetProperty);
});
export const class_deleteDerivedProperty = action((_class, val) => {
    deleteEntry(_class.derivedProperties, val);
});
export const class_addDerivedProperty = action((_class, val) => {
    addUniqueEntry(_class.derivedProperties, observe_DerivedProperty(val));
});
export const class_swapDerivedProperties = action((_class, sourceProperty, targetProperty) => {
    swapEntry(_class.derivedProperties, sourceProperty, targetProperty);
});
export const class_addContraint = action((_class, val) => {
    addUniqueEntry(_class.constraints, observe_Constraint(val));
});
export const class_deleteConstraint = action((_class, val) => {
    deleteEntry(_class.constraints, val);
});
export const class_swapConstraints = action((_class, sourceConstraint, targetConstraint) => {
    swapEntry(_class.constraints, sourceConstraint, targetConstraint);
});
export const class_addSuperType = action((_class, val) => {
    addUniqueEntry(_class.generalizations, observe_GenericTypeReference(val));
});
export const class_deleteSuperType = action((_class, val) => {
    deleteEntry(_class.generalizations, val);
});
export const class_swapSuperTypes = action((_class, sourceSuperType, targetSuperType) => {
    swapEntry(_class.generalizations, sourceSuperType, targetSuperType);
});
export const class_addSubclass = action((_class, val) => {
    addUniqueEntry(_class._subclasses, val);
});
export const class_deleteSubclass = action((_class, val) => {
    deleteEntry(_class._subclasses, val);
});
// --------------------------------------------- GenericTypeReference -------------------------------------
export const setGenericTypeReferenceValue = action((gen, value) => {
    observe_GenericTypeReference(gen);
    observe_GenericType(value);
    gen.value = value;
    gen.ownerReference.value = value.rawType;
});
// --------------------------------------------- Property ------------------------------------------------
export const property_setName = action((_property, value) => {
    _property.name = value;
});
export const property_setGenericType = action((_property, value) => {
    setGenericTypeReferenceValue(_property.genericType, observe_GenericType(value));
});
export const property_setMultiplicity = action((_property, value) => {
    _property.multiplicity = value;
});
export const property_setAggregationKind = action((target, value) => {
    target.aggregation = value;
});
export const stereotypeReference_setValue = action((sV, value) => {
    sV.value = observe_Stereotype(value);
    packageableElementReference_setValue(sV.ownerReference, value._OWNER);
});
// --------------------------------------------- AnnotatedElement -------------------------------------
export const annotatedElement_addTaggedValue = action((annotatedElement, value) => {
    addUniqueEntry(annotatedElement.taggedValues, observe_TaggedValue(value));
});
export const annotatedElement_deleteTaggedValue = action((_property, value) => {
    deleteEntry(_property.taggedValues, value);
});
export const annotatedElement_addStereotype = action((annotatedElement, value) => {
    addUniqueEntry(annotatedElement.stereotypes, observe_StereotypeReference(value));
});
export const annotatedElement_deleteStereotype = action((annotatedElement, value) => {
    deleteEntry(annotatedElement.stereotypes, value);
});
export const taggedValue_setTag = action((taggedValue, value) => {
    taggedValue.tag.value = observe_Tag(value);
    taggedValue.tag.ownerReference.value = value._OWNER;
});
export const taggedValue_setValue = action((val, value) => {
    val.value = value;
});
export const tagStereotype_setValue = action((_tag, value) => {
    _tag.value = value;
});
export const annotatedElement_swapTaggedValues = action((annotatedElement, sourceTaggedValue, targetTaggedValue) => {
    swapEntry(annotatedElement.taggedValues, sourceTaggedValue, targetTaggedValue);
});
export const annotatedElement_swapStereotypes = action((annotatedElement, sourceStereotype, targetStereotype) => {
    swapEntry(annotatedElement.stereotypes, sourceStereotype, targetStereotype);
});
// --------------------------------------------- DerivedProperty -------------------------------------
export const derivedProperty_setBody = (dp, value) => {
    dp.body = value;
};
export const derivedProperty_setParameters = (dp, value) => {
    dp.parameters = value;
};
// --------------------------------------------- Constraint -------------------------------------
export const constraint_setName = action((_constraint, name) => {
    _constraint.name = name;
});
export const constraint_setFunctionDefinition = action((_constraint, lambda) => {
    _constraint.functionDefinition = observe_RawLambda(lambda);
});
// --------------------------------------------- Profile -------------------------------------
export const profile_addTag = action((profile, value) => {
    addUniqueEntry(profile.p_tags, observe_Tag(value));
});
export const profile_deleteTag = action((profile, value) => {
    deleteEntry(profile.p_tags, value);
});
export const profile_addStereotype = action((profile, value) => {
    addUniqueEntry(profile.p_stereotypes, observe_Stereotype(value));
});
export const profile_deleteStereotype = action((profile, value) => {
    deleteEntry(profile.p_stereotypes, value);
});
export const profile_swapTags = action((profile, sourceTag, targetTag) => {
    swapEntry(profile.p_tags, sourceTag, targetTag);
});
export const profile_swapStereotypes = action((profile, sourceStereotype, targetStereotype) => {
    swapEntry(profile.p_stereotypes, sourceStereotype, targetStereotype);
});
// --------------------------------------------- Function -------------------------------------
export const function_deleteParameter = action((_func, val) => {
    deleteEntry(_func.parameters, val);
});
export const function_addParameter = action((_func, val) => {
    addUniqueEntry(_func.parameters, observe_RawVariableExpression(val));
});
export const function_setReturnGenericType = action((_func, val) => {
    setGenericTypeReferenceValue(_func.returnType, observe_GenericType(val));
});
export const function_setReturnMultiplicity = action((_func, val) => {
    _func.returnMultiplicity = val;
});
export const function_swapParameters = action((_func, sourceParameter, targetParameter) => {
    swapEntry(_func.parameters, sourceParameter, targetParameter);
});
export const INTERNAL__UnknownFunctionActivator_setContent = action((metamodel, val) => {
    metamodel.content = val;
});
export const functionTestable_setEmbeddedData = action((functionTestData, embeddedData, observerContext) => {
    functionTestData.data = observe_EmbeddedData(embeddedData, observerContext);
});
export const functionTestable_deleteDataStore = action((suite, val) => {
    deleteEntry(suite.testData ?? [], val);
});
export const function_addTestSuite = action((_func, val, context) => {
    addUniqueEntry(_func.tests, observe_FunctionTestSuite(val, context));
});
export const function_setParameterValueSpec = action((parameterValue, val) => {
    parameterValue.value = val;
});
export const function_setParameterValues = action((test, values) => {
    test.parameters = values.map(observe_FunctionParameterValue);
});
export const function_deleteParameterValue = action((test, value) => {
    deleteEntry(test.parameters ?? [], value);
});
export const function_addParameterValue = action((test, value) => {
    if (test.parameters) {
        test.parameters.push(observe_FunctionParameterValue(value));
    }
    else {
        test.parameters = [observe_FunctionParameterValue(value)];
    }
});
export const function_setParameterName = action((parameterValue, val) => {
    parameterValue.name = val;
});
// --------------------------------------------- Enumeration -------------------------------------
export const enum_setName = action((val, value) => {
    val.name = value;
});
export const enum_addValue = action((enumeration, value) => {
    addUniqueEntry(enumeration.values, observe_Enum(value));
});
export const enum_deleteValue = action((enumeration, value) => {
    deleteEntry(enumeration.values, value);
});
export const enum_swapValues = action((enumeration, sourceEnum, targetEnum) => {
    swapEntry(enumeration.values, sourceEnum, targetEnum);
});
export const enumValueReference_setValue = action((ref, value) => {
    ref.value = observe_Enum(value);
    packageableElementReference_setValue(ref.ownerReference, value._OWNER);
});
// --------------------------------------------- Association -------------------------------------
export const association_changePropertyType = action((association, property, type) => {
    const otherProperty = getOtherAssociatedProperty(association, property);
    // remove other property from current parent class of the to-be-changed property
    const otherPropertyAssociatedClass = guaranteeType(property.genericType.ownerReference.value, Class, `Association property '${property.name}' must be of type 'class'`);
    // don't invoke deletion if the class is a stub (otherProperty is not present)
    if (!isStubbed_PackageableElement(otherPropertyAssociatedClass)) {
        assertTrue(deleteEntry(otherPropertyAssociatedClass.propertiesFromAssociations, otherProperty), `Can't find property '${otherProperty.name}' from association '${association.path}' in associated class '${otherPropertyAssociatedClass.path}'`);
    }
    // set up the relationship between the other property and the new class
    addUniqueEntry(type.propertiesFromAssociations, otherProperty);
    // set new type for the property
    const _genType = new GenericType(type);
    property.genericType.value = _genType;
    property.genericType.ownerReference.value = _genType.rawType;
});
// --------------------------------------------- Measure -------------------------------------
export const measure_setCanonicalUnit = action((_measure, unit) => {
    _measure.canonicalUnit = observe_Unit(unit);
});
export const unit_setConversionFunction = action((unit, lambda) => {
    unit.conversionFunction = observe_RawLambda(lambda);
});
//# sourceMappingURL=DomainGraphModifierHelper.js.map