import { camelCase, kebabCase, lowerFirst } from 'lodash-es';
import { relationshipOptions, validations } from '../../core/built-in-options/index.js';
const { Validations: { REQUIRED }, } = validations;
const { BUILT_IN_ENTITY } = relationshipOptions;
let convertedAigcs;
export default { convert };
export function convert(jdlAigcs = [], entityNames = []) {
    if (jdlAigcs.length === 0 || entityNames.length === 0) {
        return new Map();
    }
    convertedAigcs = new Map(entityNames.map(entityName => [entityName, []]));
    const relatedAigcs = getRelatedAigcs(jdlAigcs, entityNames);
    relatedAigcs.forEach((relatedAigc, currentEntityName) => {
        setRelationshipsFromEntity(relatedAigc, currentEntityName);
    });
    return convertedAigcs;
}
function getRelatedAigcs(jdlAigcs, entityNames) {
    const relatedAigcs = new Map();
    entityNames.forEach(entityName => {
        const aigcsRelatedToEntity = {
            from: [],
            to: [],
        };
        jdlAigcs.forEach(jdlAigc => {
            if (jdlAigc.from === entityName) {
                aigcsRelatedToEntity.from.push(jdlAigc);
            }
        });
        relatedAigcs.set(entityName, aigcsRelatedToEntity);
    });
    return relatedAigcs;
}
function setRelationshipsFromEntity(relatedAigcs, entityName) {
    relatedAigcs.from.forEach(aigcToConvert => {
        const convertedAigc = {
            aigcType: kebabCase(aigcToConvert.type),
            targetType: aigcToConvert.to,
        };
        if (aigcToConvert.commentInFrom) {
            convertedAigc.documentation = aigcToConvert.commentInFrom;
        }
        const splitField = extractField(aigcToConvert.injectedFieldInFrom);
        if (splitField.aigcName) {
            convertedAigc.aigcName = splitField.aigcName;
        }
        const convertedEntityRelationships = convertedAigcs.get(entityName);
        convertedEntityRelationships.push(convertedAigc);
    });
}
export const otherRelationshipType = relationshipType => relationshipType.split('-').reverse().join('-');
function setRelationshipsToEntity(relatedRelationships, entityName) {
    relatedRelationships.to.forEach(relationshipToConvert => {
        const otherSplitField = extractField(relationshipToConvert.injectedFieldInFrom);
        const convertedRelationship = {
            relationshipSide: 'right',
            relationshipType: otherRelationshipType(kebabCase(relationshipToConvert.type)),
            otherEntityName: camelCase(relationshipToConvert.from),
        };
        if (otherSplitField.relationshipName) {
            convertedRelationship.otherEntityRelationshipName =
                lowerFirst(otherSplitField.relationshipName) || camelCase(relationshipToConvert.to);
        }
        if (relationshipToConvert.isInjectedFieldInToRequired) {
            convertedRelationship.relationshipValidateRules = REQUIRED;
        }
        if (relationshipToConvert.commentInTo) {
            convertedRelationship.documentation = relationshipToConvert.commentInTo;
        }
        const options = {};
        if (relationshipToConvert.options &&
            relationshipToConvert.options.source &&
            Object.keys(relationshipToConvert.options.source).length > 0) {
            options.source = relationshipToConvert.options.source;
        }
        if (relationshipToConvert.options &&
            relationshipToConvert.options.global &&
            Object.keys(relationshipToConvert.options.global).length > 0) {
            options.global = relationshipToConvert.options.global;
        }
        if (relationshipToConvert.options &&
            relationshipToConvert.options.destination &&
            Object.keys(relationshipToConvert.options.destination).length > 0) {
            options.destination = relationshipToConvert.options.destination;
        }
        if (Object.keys(options).length > 0) {
            convertedRelationship.options = options;
        }
        const splitField = extractField(relationshipToConvert.injectedFieldInTo);
        convertedRelationship.relationshipName = camelCase(splitField.relationshipName || relationshipToConvert.from);
        if (splitField.otherEntityField) {
            convertedRelationship.otherEntityField = lowerFirst(splitField.otherEntityField);
        }
        relationshipToConvert.injectedFieldInTo = relationshipToConvert.injectedFieldInTo ?? lowerFirst(relationshipToConvert.from);
        setOptionsForRelationshipDestinationSide(relationshipToConvert, convertedRelationship);
        const convertedEntityRelationships = convertedAigcs.get(entityName);
        convertedEntityRelationships.push(convertedRelationship);
    });
}
function setOptionsForRelationshipSourceSide(relationshipToConvert, convertedRelationship) {
    convertedRelationship.options = convertedRelationship.options || {};
    relationshipToConvert.forEachGlobalOption((optionName, optionValue) => {
        if (optionName === BUILT_IN_ENTITY) {
            convertedRelationship.relationshipWithBuiltInEntity = optionValue;
        }
        else {
            convertedRelationship.options[optionName] = optionValue;
        }
    });
    relationshipToConvert.forEachDestinationOption((optionName, optionValue) => {
        convertedRelationship.options[optionName] = optionValue;
    });
    if (Object.keys(convertedRelationship.options).length === 0) {
        delete convertedRelationship.options;
    }
}
function setOptionsForRelationshipDestinationSide(relationshipToConvert, convertedRelationship) {
    convertedRelationship.options = convertedRelationship.options || {};
    relationshipToConvert.forEachGlobalOption((optionName, optionValue) => {
        convertedRelationship.options[optionName] = optionValue;
    });
    relationshipToConvert.forEachSourceOption((optionName, optionValue) => {
        convertedRelationship.options[optionName] = optionValue;
    });
    if (Object.keys(convertedRelationship.options).length === 0) {
        delete convertedRelationship.options;
    }
}
function extractField(field) {
    const splitField = {
        aigcName: '',
    };
    if (field) {
        const chunks = field.replace('(', '/').replace(')', '').split('/');
        splitField.aigcName = chunks[0];
    }
    return splitField;
}
