import * as _ from 'lodash-es';
import { relationshipOptions, validations } from '../../jhipster/index.mjs';
import { camelCase, lowerFirst } from '../../utils/string-utils.js';
const { Validations: { REQUIRED }, } = validations;
const { BUILT_IN_ENTITY } = relationshipOptions;
let convertedRelationships;
export default { convert };
export function convert(jdlRelationships = [], entityNames = []) {
    if (jdlRelationships.length === 0 || entityNames.length === 0) {
        return new Map();
    }
    convertedRelationships = new Map(entityNames.map(entityName => [entityName, []]));
    const relatedRelationships = getRelatedRelationships(jdlRelationships, entityNames);
    relatedRelationships.forEach((relatedRelationship, currentEntityName) => {
        setRelationshipsFromEntity(relatedRelationship, currentEntityName);
        setRelationshipsToEntity(relatedRelationship, currentEntityName);
    });
    return convertedRelationships;
}
function getRelatedRelationships(relationships, entityNames) {
    const relatedRelationships = new Map();
    entityNames.forEach(entityName => {
        const relationshipsRelatedToEntity = {
            from: [],
            to: [],
        };
        relationships.forEach(jdlRelationship => {
            if (jdlRelationship.from === entityName) {
                relationshipsRelatedToEntity.from.push(jdlRelationship);
            }
            if (jdlRelationship.to === entityName &&
                (jdlRelationship.injectedFieldInTo || Object.keys(jdlRelationship.options.source).length !== 0)) {
                relationshipsRelatedToEntity.to.push(jdlRelationship);
            }
        });
        relatedRelationships.set(entityName, relationshipsRelatedToEntity);
    });
    return relatedRelationships;
}
function setRelationshipsFromEntity(relatedRelationships, entityName) {
    relatedRelationships.from.forEach(relationshipToConvert => {
        const otherSplitField = extractField(relationshipToConvert.injectedFieldInTo);
        const convertedRelationship = {
            relationshipSide: 'left',
            relationshipType: _.kebabCase(relationshipToConvert.type),
            otherEntityName: camelCase(relationshipToConvert.to),
        };
        if (otherSplitField.relationshipName) {
            convertedRelationship.otherEntityRelationshipName = lowerFirst(otherSplitField.relationshipName);
        }
        if (relationshipToConvert.isInjectedFieldInFromRequired) {
            convertedRelationship.relationshipValidateRules = REQUIRED;
        }
        if (relationshipToConvert.commentInFrom) {
            convertedRelationship.documentation = relationshipToConvert.commentInFrom;
        }
        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.injectedFieldInFrom);
        convertedRelationship.relationshipName = camelCase(splitField.relationshipName || relationshipToConvert.to);
        if (splitField.otherEntityField) {
            convertedRelationship.otherEntityField = lowerFirst(splitField.otherEntityField);
        }
        setOptionsForRelationshipSourceSide(relationshipToConvert, convertedRelationship);
        const convertedEntityRelationships = convertedRelationships.get(entityName);
        convertedEntityRelationships.push(convertedRelationship);
    });
}
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 = convertedRelationships.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 = {
        relationshipName: '',
    };
    if (field) {
        const chunks = field.replace('(', '/').replace(')', '').split('/');
        splitField.relationshipName = chunks[0];
        if (chunks.length > 1) {
            splitField.otherEntityField = chunks[1];
        }
    }
    return splitField;
}
