import * as _ from 'lodash-es';
import JDLObject from '../../models/jdl-object.js';
import JDLBinaryOption from '../../models/jdl-binary-option.js';
import { applicationTypes, binaryOptions } from '../../jhipster/index.mjs';
import { convertApplications } from './application-converter.js';
import { convertEntities } from './entity-converter.js';
import { convertEnums } from './enum-converter.js';
import { convertField } from './field-converter.js';
import { convertValidations } from './validation-converter.js';
import { convertOptions } from './option-converter.js';
import { convertRelationships } from './relationship-converter.js';
import { convertDeployments } from './deployment-converter.js';
let parsedContent;
let configuration;
let jdlObject;
let entityNames;
let applicationsPerEntityName;
export function parseFromConfigurationObject(configurationObject) {
    parsedContent = configurationObject.parsedContent || configurationObject.document;
    if (!parsedContent) {
        throw new Error('The parsed JDL content must be passed.');
    }
    init(configurationObject);
    fillApplications();
    fillDeployments();
    fillEnums();
    fillClassesAndFields();
    fillAssociations();
    fillOptions();
    return jdlObject;
}
function init(passedConfiguration) {
    configuration = passedConfiguration;
    jdlObject = new JDLObject();
    entityNames = parsedContent.entities.map(entity => entity.name);
    applicationsPerEntityName = {};
}
function fillApplications() {
    const jdlApplications = convertApplications(parsedContent.applications, configuration, entityNames);
    jdlApplications.forEach(jdlApplication => {
        jdlObject.addApplication(jdlApplication);
        fillApplicationsPerEntityName(jdlApplication);
    });
}
function fillApplicationsPerEntityName(application) {
    application.forEachEntityName(entityName => {
        applicationsPerEntityName[entityName] = applicationsPerEntityName[entityName] || [];
        applicationsPerEntityName[entityName].push(application);
    });
}
function fillDeployments() {
    const jdlDeployments = convertDeployments(parsedContent.deployments);
    jdlDeployments.forEach(jdlDeployment => {
        jdlObject.addDeployment(jdlDeployment);
    });
}
function fillEnums() {
    const jdlEnums = convertEnums(parsedContent.enums);
    jdlEnums.forEach(jdlEnum => {
        jdlObject.addEnum(jdlEnum);
    });
}
function fillClassesAndFields() {
    const jdlEntities = convertEntities(parsedContent.entities, getJDLFieldsFromParsedEntity);
    jdlEntities.forEach(jdlEntity => {
        jdlObject.addEntity(jdlEntity);
    });
}
function getJDLFieldsFromParsedEntity(entity) {
    const fields = [];
    for (let i = 0; i < entity.body.length; i++) {
        const field = entity.body[i];
        const jdlField = convertField(field);
        jdlField.validations = getValidations(field);
        jdlField.options = convertAnnotationsToOptions(field.annotations);
        fields.push(jdlField);
    }
    return fields;
}
function getValidations(field) {
    return convertValidations(field.validations, getConstantValueFromConstantName).reduce((jdlValidations, jdlValidation) => {
        jdlValidations[jdlValidation.name] = jdlValidation;
        return jdlValidations;
    }, {});
}
function getConstantValueFromConstantName(constantName) {
    return parsedContent.constants[constantName];
}
function fillAssociations() {
    const jdlRelationships = convertRelationships(parsedContent.relationships, convertAnnotationsToOptions);
    jdlRelationships.forEach(jdlRelationship => {
        jdlObject.addRelationship(jdlRelationship);
    });
}
function convertAnnotationsToOptions(annotations) {
    const result = {};
    annotations.forEach(annotation => {
        const annotationName = _.lowerFirst(annotation.optionName);
        const value = annotation.optionValue ? annotation.optionValue : true;
        if (annotationName in result) {
            const previousValue = result[annotationName];
            if (Array.isArray(previousValue)) {
                if (!previousValue.includes(value)) {
                    previousValue.push(value);
                }
            }
            else if (value !== previousValue) {
                result[annotationName] = [previousValue, value];
            }
        }
        else {
            result[annotationName] = value;
        }
    });
    return result;
}
function fillOptions() {
    if (configuration.applicationType === applicationTypes.MICROSERVICE && !parsedContent.options.microservice) {
        globallyAddMicroserviceOption(configuration.applicationName);
    }
    fillUnaryAndBinaryOptions();
}
function globallyAddMicroserviceOption(applicationName) {
    jdlObject.addOption(new JDLBinaryOption({
        name: binaryOptions.Options.MICROSERVICE,
        value: applicationName,
        entityNames,
    }));
}
function fillUnaryAndBinaryOptions() {
    if (configuration.applicationType === applicationTypes.MICROSERVICE) {
        jdlObject.addOption(new JDLBinaryOption({
            name: binaryOptions.Options.CLIENT_ROOT_FOLDER,
            value: configuration.applicationName,
            entityNames,
        }));
    }
    const convertedOptions = convertOptions(parsedContent.options, parsedContent.useOptions);
    convertedOptions.forEach(convertedOption => {
        jdlObject.addOption(convertedOption);
    });
}
export default {
    parseFromConfigurationObject,
};
