import { isFilePending } from 'mem-fs-editor/state';
import BaseApplicationGenerator from '../base-application/index.mjs';
import { GENERATOR_JAVA, GENERATOR_BOOTSTRAP_APPLICATION } from '../generator-list.mjs';
import writeTask from './files.mjs';
import cleanupTask from './cleanup.mjs';
import { packageInfoTransform, generatedAnnotationTransform, checkJava } from './support/index.mjs';
import command from './command.mjs';
import { JAVA_COMPATIBLE_VERSIONS } from '../generator-constants.mjs';
import { matchMainJavaFiles } from './support/package-info-transform.mjs';
import { entityServerFiles, enumFiles } from './entity-files.mjs';
import { getEnumInfo } from '../base-application/support/index.mjs';
import { hibernateSnakeCase } from '../server/support/index.mjs';
export default class JavaGenerator extends BaseApplicationGenerator {
    packageInfoFile;
    generateEntities;
    useJakartaValidation;
    generateEnums;
    async beforeQueue() {
        if (!this.fromBlueprint) {
            await this.composeWithBlueprints(GENERATOR_JAVA);
        }
        if (!this.delegateToBlueprint) {
            await this.dependsOnJHipster(GENERATOR_BOOTSTRAP_APPLICATION);
        }
    }
    get initializing() {
        return this.asInitializingTaskGroup({
            loadConfig() {
                this.parseJHipsterCommand(command);
            },
            validateJava() {
                if (!this.skipChecks) {
                    this.checkJava();
                }
            },
        });
    }
    get [BaseApplicationGenerator.INITIALIZING]() {
        return this.asInitializingTaskGroup(this.delegateTasksToBlueprint(() => this.initializing));
    }
    get default() {
        return this.asDefaultTaskGroup({
            generatedAnnotation({ application }) {
                if (this.jhipsterConfig.withGeneratedFlag) {
                    this.queueTransformStream(generatedAnnotationTransform(application.packageName), {
                        name: 'adding @GeneratedByJHipster annotations',
                        streamOptions: { filter: file => isFilePending(file) && file.path.endsWith('.java') },
                    });
                }
            },
            generatedPackageInfo({ application }) {
                const mainPackageMatch = matchMainJavaFiles(application.srcMainJava);
                if (this.packageInfoFile) {
                    this.queueTransformStream(packageInfoTransform({
                        javaRoots: [this.destinationPath(application.srcMainJava)],
                        editor: this.fs,
                        javadocs: {
                            ...Object.fromEntries(application.packageInfoJavadocs.map(doc => [doc.packageName, doc.documentation])),
                            [`${application.packageName}`]: 'Application root.',
                            [`${application.packageName}.config`]: 'Application configuration.',
                            [`${application.packageName}.domain`]: 'Domain objects.',
                            [`${application.packageName}.repository`]: 'Repository layer.',
                            [`${application.packageName}.service`]: 'Service layer.',
                            [`${application.packageName}.web.rest`]: 'Rest layer.',
                        },
                    }), {
                        name: 'adding package-info.java files',
                        streamOptions: {
                            filter: file => isFilePending(file) && !file.path.endsWith('package-info.java') && mainPackageMatch.match(file.path),
                        },
                    });
                }
            },
        });
    }
    get [BaseApplicationGenerator.DEFAULT]() {
        return this.delegateTasksToBlueprint(() => this.default);
    }
    get writing() {
        return this.asWritingTaskGroup({
            cleanupTask,
            writeTask,
        });
    }
    get [BaseApplicationGenerator.WRITING]() {
        return this.delegateTasksToBlueprint(() => this.writing);
    }
    get writingEntities() {
        return this.asWritingEntitiesTaskGroup({
            async writeServerFiles({ application, entities }) {
                if (!this.generateEntities)
                    return;
                const { useJakartaValidation } = this;
                for (const entity of entities.filter(entity => !entity.skipServer && !entity.builtIn)) {
                    await this.writeFiles({
                        sections: entityServerFiles,
                        context: { ...application, ...entity, useJakartaValidation },
                    });
                }
            },
            async writeEnumFiles({ application, entities }) {
                if (!this.generateEnums || !this.generateEntities)
                    return;
                for (const entity of entities.filter(entity => !entity.skipServer)) {
                    for (const field of entity.fields.filter(field => field.fieldIsEnum)) {
                        const enumInfo = {
                            ...getEnumInfo(field, entity.clientRootFolder),
                            frontendAppName: entity.frontendAppName,
                            packageName: application.packageName,
                            javaPackageSrcDir: application.javaPackageSrcDir,
                            entityJavaPackageFolder: entity.entityJavaPackageFolder,
                            entityAbsolutePackage: application.packageName,
                            ormTool: application.ormTool,
                            fromDict: field.options && field.options.fromDict || false,
                        };
                        const splitNames = application.dasherizedBaseName.split('-');
                        splitNames.pop();
                        const projectName = splitNames.join('-');
                        await this.writeFiles({
                            sections: enumFiles,
                            context: enumInfo,
                        });
                    }
                }
            },
        });
    }
    get [BaseApplicationGenerator.WRITING_ENTITIES]() {
        return this.delegateTasksToBlueprint(() => this.writingEntities);
    }
    checkJava(javaCompatibleVersions = JAVA_COMPATIBLE_VERSIONS, checkResultValidation) {
        this.validateResult(checkJava(javaCompatibleVersions), { throwOnError: false, ...checkResultValidation });
    }
    getColumnName(value) {
        return hibernateSnakeCase(value);
    }
}
