import { isFileStateModified } from 'mem-fs-editor/state';
import BaseApplicationGenerator from '../../../base-application/index.js';
import { JAVA_COMPATIBLE_VERSIONS } from '../../../generator-constants.js';
import { packageInfoTransform, generatedAnnotationTransform, checkJava, isReservedJavaKeyword, matchMainJavaFiles, javaMainPackageTemplatesBlock, addJavaImport, addJavaAnnotation, } from '../../support/index.js';
export default class BootstrapGenerator extends BaseApplicationGenerator {
    packageInfoFile;
    async beforeQueue() {
        if (!this.fromBlueprint) {
            await this.composeWithBlueprints();
        }
        if (!this.delegateToBlueprint) {
            await this.dependsOnBootstrapApplication();
        }
    }
    get initializing() {
        return this.asInitializingTaskGroup({
            async parseCommand() {
                await this.parseCurrentJHipsterCommand();
            },
            validateJava() {
                if (!this.skipChecks) {
                    this.checkJava();
                }
            },
        });
    }
    get [BaseApplicationGenerator.INITIALIZING]() {
        return this.delegateTasksToBlueprint(() => this.initializing);
    }
    get prompting() {
        return this.asPromptingTaskGroup({
            async promptCommand({ control }) {
                if (control.existingProject && this.options.askAnswered !== true)
                    return;
                await this.promptCurrentJHipsterCommand();
            },
        });
    }
    get [BaseApplicationGenerator.PROMPTING]() {
        return this.delegateTasksToBlueprint(() => this.prompting);
    }
    get configuring() {
        return this.asConfiguringTaskGroup({
            checkConfig() {
                const { packageName } = this.jhipsterConfigWithDefaults;
                const reservedKeywork = packageName.split('.').find(isReservedJavaKeyword);
                if (reservedKeywork) {
                    throw new Error(`The package name "${packageName}" contains a reserved Java keyword "${reservedKeywork}".`);
                }
            },
        });
    }
    get [BaseApplicationGenerator.CONFIGURING]() {
        return this.delegateTasksToBlueprint(() => this.configuring);
    }
    get loading() {
        return this.asLoadingTaskGroup({
            async loadConfig({ application }) {
                await this.loadCurrentJHipsterCommandConfig(application);
            },
        });
    }
    get [BaseApplicationGenerator.LOADING]() {
        return this.delegateTasksToBlueprint(() => this.loading);
    }
    get preparing() {
        return this.asPreparingTaskGroup({
            prepareJavaApplication({ application, source }) {
                source.hasJavaProperty = (property) => application.javaProperties[property] !== undefined;
                source.hasJavaManagedProperty = (property) => application.javaManagedProperties[property] !== undefined;
            },
            needles({ source }) {
                source.editJavaFile = (file, { staticImports = [], imports = [], annotations = [] }, ...editFileCallback) => this.editFile(file, ...staticImports.map(classPath => addJavaImport(classPath, { staticImport: true })), ...imports.map(classPath => addJavaImport(classPath)), ...annotations.map(annotation => addJavaAnnotation(annotation)), ...editFileCallback);
            },
        });
    }
    get [BaseApplicationGenerator.PREPARING]() {
        return this.delegateTasksToBlueprint(() => this.preparing);
    }
    get default() {
        return this.asDefaultTaskGroup({
            loadDomains({ application, entities }) {
                const entityPackages = [
                    ...new Set([application.packageName, ...entities.map(entity => entity.entityAbsolutePackage).filter(Boolean)]),
                ];
                application.entityPackages = entityPackages;
                application.domains = entityPackages;
            },
            generatedAnnotation({ application }) {
                if (this.jhipsterConfig.withGeneratedFlag && application.backendTypeJavaAny) {
                    this.queueTransformStream({
                        name: 'adding @GeneratedByJHipster annotations',
                        filter: file => isFileStateModified(file) && file.path.startsWith(this.destinationPath()) && file.path.endsWith('.java'),
                        refresh: false,
                    }, generatedAnnotationTransform(application.packageName));
                }
            },
            generatedPackageInfo({ application }) {
                if (!application.backendTypeJavaAny)
                    return;
                const { srcMainJava } = application;
                if (this.packageInfoFile && srcMainJava) {
                    const mainPackageMatch = matchMainJavaFiles(srcMainJava);
                    const root = this.destinationPath(srcMainJava);
                    this.queueTransformStream({
                        name: 'adding package-info.java files',
                        filter: file => isFileStateModified(file) && file.path.startsWith(this.destinationPath()) && mainPackageMatch.match(file.path),
                        refresh: true,
                    }, packageInfoTransform({
                        javaRoots: [root],
                        javadocs: {
                            ...Object.fromEntries(application.packageInfoJavadocs.map(doc => [doc.packageName, doc.documentation])),
                            [`${application.packageName}`]: 'Application root.',
                            [`${application.packageName}.config`]: 'Application configuration.',
                            ...Object.fromEntries(application
                                .entityPackages.map(pkg => [
                                [`${pkg}.domain`, 'Domain objects.'],
                                [`${pkg}.repository`, 'Repository layer.'],
                                [`${pkg}.service`, 'Service layer.'],
                                [`${pkg}.web.rest`, 'Rest layer.'],
                            ])
                                .flat()),
                        },
                    }));
                }
            },
        });
    }
    get [BaseApplicationGenerator.DEFAULT]() {
        return this.delegateTasksToBlueprint(() => this.default);
    }
    get writing() {
        return this.asWritingTaskGroup({
            async writing({ application }) {
                if (!application.backendTypeJavaAny)
                    return;
                await this.writeFiles({
                    blocks: [
                        javaMainPackageTemplatesBlock({
                            templates: ['GeneratedByJHipster.java'],
                        }),
                    ],
                    context: application,
                });
            },
        });
    }
    get [BaseApplicationGenerator.WRITING]() {
        return this.delegateTasksToBlueprint(() => this.writing);
    }
    checkJava(javaCompatibleVersions = JAVA_COMPATIBLE_VERSIONS, checkResultValidation) {
        this.validateResult(checkJava(javaCompatibleVersions), { throwOnError: false, ...checkResultValidation });
    }
}
