/**
 * 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 { UnsupportedOperationError } from '@finos/legend-shared';
import { DataElementReference, ExternalFormatData, ModelStoreData, ModelEmbeddedData, ModelInstanceData, RelationElementsData, } from '../../../../../../../graph/metamodel/pure/data/EmbeddedData.js';
import { RelationalCSVData, } from '../../../../../../../graph/metamodel/pure/data/RelationalCSVData.js';
import { DataElement } from '../../../../../../../graph/metamodel/pure/packageableElements/data/DataElement.js';
import { V1_DataElementReference, V1_ExternalFormatData, V1_ModelStoreData, V1_ModelEmbeddedData, V1_ModelInstanceData, V1_RelationElementsData, V1_RelationElement, V1_RelationRowTestData, } from '../../../model/data/V1_EmbeddedData.js';
import { V1_RelationalCSVData, V1_RelationalCSVDataTable, } from '../../../model/data/V1_RelationalCSVData.js';
import { V1_DataElement } from '../../../model/packageableElements/data/V1_DataElement.js';
import { V1_initPackageableElement, V1_transformElementReferencePointer, } from './V1_CoreTransformerHelper.js';
import { V1_transformStereotype, V1_transformTaggedValue, } from './V1_DomainTransformer.js';
import { INTERNAL__UnknownEmbeddedData } from '../../../../../../../graph/metamodel/pure/data/INTERNAL__UnknownEmbeddedData.js';
import { V1_INTERNAL__UnknownEmbeddedData } from '../../../model/data/V1_INTERNAL__UnknownEmbeddedData.js';
import { PackageableElementPointerType } from '../../../../../../../graph/MetaModelConst.js';
// ----------------------------------------------- DATA ----------------------------------------
const V1_transformModelInstanceData = (element) => {
    const val = new V1_ModelInstanceData();
    val.model = element.model.valueForSerialization ?? '';
    val.instances = element.instances;
    return val;
};
const V1_transformModelEmbeddedData = (element, context) => {
    const val = new V1_ModelEmbeddedData();
    val.data = V1_transformEmbeddedData(element.data, context);
    val.model = element.model.valueForSerialization ?? '';
    return val;
};
const V1_transformModelData = (element, context) => {
    if (element instanceof ModelInstanceData) {
        return V1_transformModelInstanceData(element);
    }
    else if (element instanceof ModelEmbeddedData) {
        return V1_transformModelEmbeddedData(element, context);
    }
    throw new UnsupportedOperationError('Model Data type not supported');
};
const V1_transformModelStoreData = (element, context) => {
    const modelStoreDataElement = new V1_ModelStoreData();
    if (element.modelData?.length) {
        modelStoreDataElement.modelData = element.modelData.map((m) => V1_transformModelData(m, context));
    }
    return modelStoreDataElement;
};
const V1_transformRelationRowTestData = (element, context) => {
    const relationRowTestData = new V1_RelationRowTestData();
    relationRowTestData.values = element.values;
    return relationRowTestData;
};
const V1_transformRelationElement = (element, context) => {
    const relationElement = new V1_RelationElement();
    relationElement.paths = element.paths;
    relationElement.columns = element.columns;
    relationElement.rows = element.rows.map((row) => V1_transformRelationRowTestData(row, context));
    return relationElement;
};
const V1_transformRelationElementsData = (element, context) => {
    const relationElementsDataElement = new V1_RelationElementsData();
    relationElementsDataElement.relationElements = element.relationElements.map((relationElement) => V1_transformRelationElement(relationElement, context));
    return relationElementsDataElement;
};
export const V1_transformExternalFormatData = (element) => {
    const externalFormatDataElement = new V1_ExternalFormatData();
    externalFormatDataElement.contentType = element.contentType;
    externalFormatDataElement.data = element.data;
    return externalFormatDataElement;
};
const V1_transformDataElementReference = (element, context) => {
    const dataElementReference = new V1_DataElementReference();
    const val = element.dataElement.value;
    if (val instanceof DataElement) {
        dataElementReference.dataElement = V1_transformElementReferencePointer(PackageableElementPointerType.DATA, element.dataElement);
        return dataElementReference;
    }
    const extraEmbeddedDataTransformers = context.plugins.flatMap((plugin) => plugin.V1_getExtraElementPointerTypes?.() ?? []);
    let type;
    for (const transformer of extraEmbeddedDataTransformers) {
        type = transformer(val);
        if (type) {
            break;
        }
    }
    if (!type) {
        throw new UnsupportedOperationError(`No packagable pointer found for element: ${element.dataElement.valueForSerialization}`);
    }
    dataElementReference.dataElement = V1_transformElementReferencePointer(type, element.dataElement);
    return dataElementReference;
};
const V1_transformRelationalCSVDataTable = (element) => {
    const table = new V1_RelationalCSVDataTable();
    table.table = element.table;
    table.schema = element.schema;
    table.values = element.values;
    return table;
};
const V1_transformRelationalCSVData = (element) => {
    const data = new V1_RelationalCSVData();
    data.tables = element.tables.map(V1_transformRelationalCSVDataTable);
    return data;
};
export function V1_transformEmbeddedData(metamodel, context) {
    if (metamodel instanceof INTERNAL__UnknownEmbeddedData) {
        const protocol = new V1_INTERNAL__UnknownEmbeddedData();
        protocol.content = metamodel.content;
        return protocol;
    }
    else if (metamodel instanceof ModelStoreData) {
        return V1_transformModelStoreData(metamodel, context);
    }
    else if (metamodel instanceof ExternalFormatData) {
        return V1_transformExternalFormatData(metamodel);
    }
    else if (metamodel instanceof RelationElementsData) {
        return V1_transformRelationElementsData(metamodel, context);
    }
    else if (metamodel instanceof DataElementReference) {
        return V1_transformDataElementReference(metamodel, context);
    }
    else if (metamodel instanceof RelationalCSVData) {
        return V1_transformRelationalCSVData(metamodel);
    }
    const extraEmbeddedDataTransformers = context.plugins.flatMap((plugin) => plugin.V1_getExtraEmbeddedDataTransformers?.() ?? []);
    for (const transformer of extraEmbeddedDataTransformers) {
        const protocol = transformer(metamodel, context);
        if (protocol) {
            return protocol;
        }
    }
    throw new UnsupportedOperationError(`Can't transform embedded data: no compatible transformer available from plugins`, metamodel);
}
export const V1_transformDataElement = (element, context) => {
    const dataElement = new V1_DataElement();
    V1_initPackageableElement(dataElement, element);
    dataElement.stereotypes = element.stereotypes.map(V1_transformStereotype);
    dataElement.taggedValues = element.taggedValues.map(V1_transformTaggedValue);
    dataElement.data = V1_transformEmbeddedData(element.data, context);
    return dataElement;
};
//# sourceMappingURL=V1_DataElementTransformer.js.map