import logger from '../../utils/objects/logger.js';
import { unaryOptions, binaryOptions, entityOptions, searchEngineTypes } from '../../jhipster/index.mjs';
const { FILTER, NO_FLUENT_METHOD, READ_ONLY, EMBEDDED, SKIP_CLIENT, SKIP_SERVER } = unaryOptions;
const { ServiceTypes } = entityOptions;
const { NO: NO_SEARCH_ENGINE } = searchEngineTypes;
const NO_SERVICE = ServiceTypes.NO;
const { Options: { ANGULAR_SUFFIX, MICROSERVICE, SEARCH, DTO }, } = binaryOptions;
const serviceClassOptionValue = binaryOptions.Values.service.SERVICE_CLASS;
let convertedOptionContent;
export default { convert };
export function convert(jdlOptionHolder) {
    if (!jdlOptionHolder) {
        throw new Error('A JDL object or application must be passed to convert JDL options to JSON.');
    }
    convertedOptionContent = new Map();
    resolveEntityNamesForEachOption(jdlOptionHolder);
    setConvertedOptionContents(jdlOptionHolder);
    return convertedOptionContent;
}
function resolveEntityNamesForEachOption(jdlOptionHolder) {
    jdlOptionHolder.forEachOption(jdlOption => {
        if (jdlOption.entityNames.has('*')) {
            jdlOption.setEntityNames(jdlOptionHolder.getEntityNames().filter(entityName => !jdlOption.excludedNames.has(entityName)));
        }
    });
}
function setConvertedOptionContents(jdlOptionHolder) {
    jdlOptionHolder.forEachOption(jdlOption => {
        setOptionsToEachEntityName(jdlOption);
    });
}
function setOptionsToEachEntityName(jdlOption) {
    const { key, value } = getJSONOptionKeyAndValue(jdlOption);
    jdlOption.entityNames.forEach(entityName => {
        setOptionToEntityName({ optionName: key, optionValue: value }, entityName);
    });
    jdlOption.entityNames.forEach(entityName => {
        const serviceOptionValue = convertedOptionContent.get(entityName).service;
        if ((!serviceOptionValue || serviceOptionValue === NO_SERVICE) && [DTO, FILTER].includes(jdlOption.name)) {
            logger.info(`The ${jdlOption.name} option is set for ${entityName}, the '${serviceClassOptionValue}' value for the ` +
                "'service' is gonna be set for this entity if no other value has been set.");
            setOptionToEntityName({ optionName: 'service', optionValue: serviceClassOptionValue }, entityName);
        }
    });
    if (jdlOption.name === SEARCH) {
        preventEntitiesFromBeingSearched(jdlOption.excludedNames);
    }
}
function getJSONOptionKeyAndValue(jdlOption) {
    switch (jdlOption.name) {
        case SKIP_CLIENT:
        case SKIP_SERVER:
        case READ_ONLY:
        case EMBEDDED:
            return { key: jdlOption.name, value: true };
        case MICROSERVICE:
            return { key: 'microserviceName', value: jdlOption.value };
        case NO_FLUENT_METHOD:
            return { key: 'fluentMethods', value: false };
        case ANGULAR_SUFFIX:
            return { key: 'angularJSSuffix', value: jdlOption.value };
        case SEARCH:
            return { key: 'searchEngine', value: jdlOption.value };
        case FILTER:
            return { key: 'jpaMetamodelFiltering', value: true };
        default:
            return { key: jdlOption.name, value: jdlOption.value || true };
    }
}
function preventEntitiesFromBeingSearched(entityNames) {
    entityNames.forEach(entityName => {
        setOptionToEntityName({ optionName: 'searchEngine', optionValue: NO_SEARCH_ENGINE }, entityName);
    });
}
function setOptionToEntityName(option, entityName) {
    const { optionName, optionValue } = option;
    const optionContentForEntity = convertedOptionContent.get(entityName) || {};
    optionContentForEntity[optionName] = optionValue;
    convertedOptionContent.set(entityName, optionContentForEntity);
}
