import { buildToolTypes } from '../../../../lib/jhipster/index.js';
import BaseApplicationGenerator from '../../../base-application/index.js';
import { GENERATOR_GRADLE, GENERATOR_MAVEN } from '../../../generator-list.js';
import { javaScopeToGradleScope } from '../../support/index.js';
const { GRADLE, MAVEN } = buildToolTypes;
export default class BuildToolGenerator extends BaseApplicationGenerator {
    async beforeQueue() {
        if (!this.fromBlueprint) {
            await this.composeWithBlueprints();
        }
        if (!this.delegateToBlueprint) {
            await this.dependsOnJHipster('begcode:java:bootstrap');
        }
    }
    get composing() {
        return this.asComposingTaskGroup({
            async composing() {
                const { buildTool } = this.jhipsterConfigWithDefaults;
                if (buildTool === GRADLE) {
                    await this.composeWithJHipster(GENERATOR_GRADLE);
                }
                else if (buildTool === MAVEN) {
                    await this.composeWithJHipster(GENERATOR_MAVEN);
                }
                else {
                    throw new Error(`Build tool ${buildTool} is not supported`);
                }
            },
        });
    }
    get [BaseApplicationGenerator.COMPOSING]() {
        return this.delegateTasksToBlueprint(() => this.composing);
    }
    get preparing() {
        return this.asPreparingTaskGroup({
            prepareJavaApplication({ application, source }) {
                source.addJavaDependencies = (dependencies, options) => {
                    if (application.buildToolMaven) {
                        const convertVersionToMavenDependency = ({ versionRef, version, exclusions, ...artifact }) => {
                            versionRef ??= version ? artifact.artifactId : undefined;
                            version = versionRef ? `\${${versionRef}.version}` : undefined;
                            const additionalContent = exclusions?.length
                                ? `<exclusions>${exclusions.map(e => `
                <exclusion>
                    <groupId>${e.groupId}</groupId>
                    <artifactId>${e.artifactId}</artifactId>
                </exclusion>`)}
                </exclusions>`
                                : '';
                            return additionalContent ? { ...artifact, version, additionalContent } : { ...artifact, version };
                        };
                        const removeScope = ({ scope: _scope, ...artifact }) => artifact;
                        const properties = dependencies
                            .filter(dep => dep.version)
                            .map(({ artifactId, version }) => ({ property: `${artifactId}.version`, value: version }));
                        const annotationProcessors = dependencies
                            .filter(dep => dep.scope === 'annotationProcessor')
                            .map(removeScope)
                            .map(convertVersionToMavenDependency);
                        const dependencyManagement = dependencies.filter(dep => dep.scope === 'import').map(convertVersionToMavenDependency);
                        const commonDependencies = dependencies
                            .filter(dep => !['annotationProcessor', 'import'].includes(dep.scope))
                            .map(convertVersionToMavenDependency);
                        source.addMavenDefinition?.({
                            properties,
                            dependencies: [
                                ...commonDependencies,
                                ...annotationProcessors.filter(dep => !dep.version).map(artifact => ({ ...artifact, scope: 'provided' })),
                            ],
                            dependencyManagement,
                            annotationProcessors,
                        });
                    }
                    if (application.buildToolGradle) {
                        const gradleDependencies = dependencies.map(({ exclusions, ...dep }) => ({
                            ...dep,
                            closure: exclusions?.map(({ groupId, artifactId }) => `    exclude group: '${groupId}', module: '${artifactId}'`),
                        }));
                        source.addGradleDependencies?.(gradleDependencies
                            .filter(dep => !dep.version && !dep.versionRef)
                            .map(({ scope, type, ...artifact }) => ({
                            ...artifact,
                            scope: javaScopeToGradleScope({ scope, type }),
                        })), options);
                        source.addGradleDependencyCatalogLibraries?.(gradleDependencies
                            .filter(dep => dep.version || dep.versionRef)
                            .map(({ scope, type, groupId, artifactId, version, versionRef, closure }) => {
                            const library = {
                                libraryName: artifactId,
                                module: `${groupId}:${artifactId}`,
                                scope: javaScopeToGradleScope({ scope, type }),
                                closure,
                            };
                            return version ? { ...library, version } : { ...library, 'version.ref': versionRef };
                        }), options);
                    }
                };
                source.addJavaDefinition = (definition, options) => {
                    const { dependencies, versions, mavenDefinition } = definition;
                    if (dependencies) {
                        source.addJavaDependencies(dependencies.filter(dep => {
                            if (dep.versionRef) {
                                return versions?.find(({ name }) => name === dep.versionRef)?.version;
                            }
                            return true;
                        }), options);
                    }
                    if (versions) {
                        if (application.buildToolMaven) {
                            source.addMavenDefinition({
                                properties: versions.filter(v => v.version).map(({ name, version }) => ({ property: `${name}.version`, value: version })),
                            });
                        }
                        if (application.buildToolGradle) {
                            source.addGradleDependencyCatalogVersions(versions, options);
                        }
                    }
                    if (application.buildToolMaven && mavenDefinition) {
                        source.addMavenDefinition(mavenDefinition);
                    }
                };
                source.addJavaDefinitions = (optionsOrDefinition, ...definitions) => {
                    let options = undefined;
                    if ('gradleFile' in optionsOrDefinition || 'gradleVersionCatalogFile' in optionsOrDefinition) {
                        options = optionsOrDefinition;
                    }
                    else {
                        definitions.unshift(optionsOrDefinition);
                    }
                    for (const definition of definitions) {
                        if (definition.condition ?? true) {
                            source.addJavaDefinition(definition, options);
                        }
                    }
                };
            },
            executable({ application }) {
                application.buildToolExecutable = application.buildToolGradle ? 'gradlew' : 'mvnw';
            },
        });
    }
    get [BaseApplicationGenerator.PREPARING]() {
        return this.delegateTasksToBlueprint(() => this.preparing);
    }
}
