//#region imports
import { RegionRemover } from 'isomorphic-region-loader/lib';
import { config, extAllowedToReplace, TAGS, UtilsFilesFoldersSync, } from 'tnp-core/lib';
import { CoreModels, _, crossPlatformPath, glob, path } from 'tnp-core/lib';
import { fileName } from 'tnp-core/lib';
import { Helpers, HelpersTaon, UtilsTypescript, UtilsZip, } from 'tnp-helpers/lib';
import { binMainProject, BundledFiles, BundledDocsFolders, dotGitIgnoreMainProject, dotNpmIgnoreMainProject, dotNpmrcMainProject, dotVscodeMainProject, localReleaseMainProject, packageJsonMainProject, readmeMdMainProject, srcMainProject, suffixLatest, tsconfigJsonBrowserMainProject, tsconfigJsonIsomorphicMainProject, tsconfigJsonMainProject, tmpCutReleaseSrcDistWebsql, tmpCutReleaseSrcDist, } from '../../../constants';
//#endregion
export class BaseArtifact {
    project;
    currentArtifactName;
    constructor(project, currentArtifactName) {
        this.project = project;
        this.currentArtifactName = currentArtifactName;
    }
    artifacts;
    globalHelper;
    //#endregion
    //#region update resolved version
    updateResolvedVersion(releaseOptions) {
        // @ts-ignore
        releaseOptions.release.resolvedNewVersion =
            this.project.packageJson.resolvePossibleNewVersion(releaseOptions.release.releaseVersionBumpType);
        this.project.packageJson.setVersion(releaseOptions.release.resolvedNewVersion);
        return releaseOptions;
    }
    //#endregion
    //#region should skip  build
    shouldSkipBuild(releaseOptions) {
        if (_.isBoolean(releaseOptions.release.skipBuildingArtifacts)) {
            return releaseOptions.release.skipBuildingArtifacts;
        }
        if (_.isArray(releaseOptions.release.skipBuildingArtifacts)) {
            return (releaseOptions.release.skipBuildingArtifacts.includes(this.currentArtifactName) ||
                releaseOptions.release.skipBuildingArtifacts.includes(releaseOptions.release.targetArtifact));
        }
        return false;
    }
    //#endregion
    //#region private methods / get static pages cloned project location
    async getStaticPagesClonedProjectLocation(releaseOptions) {
        //#region @backendFunc
        const staticPagesRepoBranch = `${releaseOptions.release.envName + (releaseOptions.release.envNumber || '')}-${releaseOptions.release.releaseType}-${this.currentArtifactName}`;
        const repoRoot = this.project.pathFor([
            `.${config.frameworkName}`,
            this.currentArtifactName,
        ]);
        const repoName = `repo-${this.project.name}-for-${releaseOptions.release.releaseType}--env-${releaseOptions.release.envName}${releaseOptions.release.envNumber || ''}`;
        const repoPath = crossPlatformPath([repoRoot, repoName]);
        const repoUrl = releaseOptions.release.staticPagesCustomRepoUrl
            ? releaseOptions.release.staticPagesCustomRepoUrl
            : this.project.git.remoteOriginUrl;
        if (!Helpers.exists(repoPath)) {
            Helpers.mkdirp(repoRoot);
            await HelpersTaon.git.clone({
                cwd: repoRoot,
                url: repoUrl,
                override: true,
                destinationFolderName: repoName,
            });
        }
        HelpersTaon.git.resetHard(repoPath);
        HelpersTaon.git.checkout(repoPath, staticPagesRepoBranch, {
            createBranchIfNotExists: true,
            fetchBeforeCheckout: true,
            switchBranchWhenExists: true,
        });
        return repoPath;
        //#endregion
    }
    //#endregion
    //#region getters & methods / all resources
    get __allResources() {
        //#region @backendFunc
        const res = [
            packageJsonMainProject,
            tsconfigJsonMainProject,
            tsconfigJsonBrowserMainProject,
            tsconfigJsonIsomorphicMainProject,
            dotNpmrcMainProject,
            dotNpmIgnoreMainProject,
            dotGitIgnoreMainProject,
            fileName.environment_js,
            fileName.tnpEnvironment_json, // TODO NOT NEEDED ?
            binMainProject,
            dotVscodeMainProject,
            ...this.project.taonJson.resources,
        ];
        return res;
        //#endregion
    }
    //#endregion
    //#region getters & methods / cut release code
    __restoreCuttedReleaseCodeFromSrc(buildOptions) {
        //#region @backend
        const releaseSrcLocation = this.project.pathFor(srcMainProject);
        const releaseSrcLocationOrg = this.project.pathFor(
        // buildOptions.temporarySrcForReleaseCutCode,
        buildOptions.build.websql
            ? tmpCutReleaseSrcDistWebsql
            : tmpCutReleaseSrcDist);
        Helpers.removeFolderIfExists(releaseSrcLocation);
        HelpersTaon.copy(releaseSrcLocationOrg, releaseSrcLocation);
        //#endregion
    }
    __cutReleaseCodeFromSrc(buildOptions) {
        //#region @backend
        const releaseSrcLocation = this.project.pathFor(srcMainProject);
        const releaseSrcLocationOrg = this.project.pathFor(buildOptions.build.websql
            ? tmpCutReleaseSrcDistWebsql
            : tmpCutReleaseSrcDist);
        Helpers.removeFolderIfExists(releaseSrcLocationOrg);
        HelpersTaon.copy(releaseSrcLocation, releaseSrcLocationOrg, {
            copySymlinksAsFiles: true,
            copySymlinksAsFilesDeleteUnexistedLinksFromSourceFirst: true,
            recursive: true,
        });
        Helpers.removeFolderIfExists(releaseSrcLocation);
        HelpersTaon.copy(releaseSrcLocationOrg, releaseSrcLocation);
        const filesForModyficaiton = glob.sync(`${releaseSrcLocation}/**/*`);
        filesForModyficaiton
            .filter(absolutePath => !Helpers.isFolder(absolutePath) &&
            extAllowedToReplace.includes(path.extname(absolutePath)))
            .forEach(absolutePath => {
            let rawContent = Helpers.readFile(absolutePath);
            rawContent = RegionRemover.from(absolutePath, rawContent, [TAGS.NOT_FOR_NPM], this).output;
            // rawContent = this.replaceRegionsWith(rawContent, ['@notFor'+'Npm']);
            Helpers.writeFile(absolutePath, rawContent);
        });
        //#endregion
    }
    //#endregion
    //#region getters & methods / distinct architecture prefix
    getDistinctArchitecturePrefix(options, includeDashEnTheEnd = false) {
        //#region @backendFunc
        options = options || {};
        if (typeof options === 'boolean' && options) {
            return `${process.platform}-${process.arch}${includeDashEnTheEnd ? '-' : ''}`;
        }
        options = options;
        if (options.arch || options.platform) {
            return ([options.platform, options.arch].filter(f => !!f).join('-') +
                `${includeDashEnTheEnd ? '-' : ''}`);
        }
        return '';
        //#endregion
    }
    //#endregion
    //#region local release deploy
    async localReleaseDeploy(outputFromBuildAbsPath, releaseOptions, options) {
        //#region @backendFunc
        let releaseProjPath;
        const projectsReposToPushAndTag = [this.project.location];
        const projectsReposToPush = [];
        const architecturePrefix = this.getDistinctArchitecturePrefix(options.distinctArchitecturePrefix, false);
        let localReleaseOutputBasePath = this.project.pathFor([
            localReleaseMainProject,
            this.currentArtifactName,
            `${this.project.name}${suffixLatest}`,
            architecturePrefix,
        ]);
        if (releaseOptions.release.useLocalReleaseBranch) {
            //#region clone proper branch
            const branchName = `release/${releaseOptions.release.releaseType}/${this.project.name}--` +
                `env-${releaseOptions.release.envName}${releaseOptions.release.envNumber || ''}`;
            const repoName = `${this.project.name}-${releaseOptions.release.envName}${releaseOptions.release.envNumber || ''}`;
            const repoRoot = this.project.pathFor([
                `.${config.frameworkName}`,
                this.currentArtifactName,
                releaseOptions.release.releaseType,
            ]);
            const repoPath = crossPlatformPath([repoRoot, repoName]);
            const repoUrl = this.project.git.remoteOriginUrl;
            if (!Helpers.exists(repoPath)) {
                Helpers.mkdirp(repoRoot);
                await HelpersTaon.git.clone({
                    cwd: repoRoot,
                    url: repoUrl,
                    override: true,
                    destinationFolderName: repoName,
                });
            }
            HelpersTaon.git.resetHard(repoPath);
            HelpersTaon.git.checkout(repoPath, branchName, {
                createBranchIfNotExists: true,
                fetchBeforeCheckout: true,
                switchBranchWhenExists: true,
            });
            //#endregion
            localReleaseOutputBasePath = crossPlatformPath([
                repoPath,
                localReleaseMainProject,
                this.currentArtifactName,
                `${this.project.name}${suffixLatest}`,
                architecturePrefix,
            ]);
            projectsReposToPush.push(repoPath);
        }
        Helpers.remove(localReleaseOutputBasePath);
        if (options.copyOnlyExtensions) {
            const zips = Helpers.getFilesFrom(outputFromBuildAbsPath, {
                recursive: false,
            }).filter(f => options.copyOnlyExtensions.some(ext => path.extname(f).replace('.', '') === ext.replace('.', '')));
            for (const zipFile of zips) {
                const fileName = path.basename(zipFile);
                const destZipFile = crossPlatformPath([
                    localReleaseOutputBasePath,
                    fileName,
                ]);
                HelpersTaon.copyFile(zipFile, destZipFile);
                if (await UtilsZip.splitFile7Zip(destZipFile)) {
                    Helpers.removeIfExists(destZipFile);
                }
            }
        }
        else {
            HelpersTaon.copy(outputFromBuildAbsPath, localReleaseOutputBasePath, {
                recursive: true,
                overwrite: true,
                copySymlinksAsFiles: true,
            });
        }
        if (options.createReadme) {
            Helpers.writeFile(crossPlatformPath([localReleaseOutputBasePath, readmeMdMainProject]), options.createReadme);
        }
        releaseProjPath = localReleaseOutputBasePath;
        return {
            releaseProjPath,
            projectsReposToPush,
            projectsReposToPushAndTag,
        };
        //#endregion
    }
    //#endregion
    //#region static pages deploy
    async staticPagesDeploy(outputFromBuildAbsPath, releaseOptions, options) {
        //#region @backendFunc
        options = options || {};
        const architecturePrefix = this.getDistinctArchitecturePrefix(options.distinctArchitecturePrefix);
        const projectsReposToPush = [];
        let releaseProjPath;
        const staticPagesProjLocation = await this.getStaticPagesClonedProjectLocation(releaseOptions);
        try {
            await HelpersTaon.git.pullCurrentBranch(staticPagesProjLocation, {
                // @ts-ignore TODO @REMOVE
                exitOnError: false,
            });
        }
        catch (error) { }
        HelpersTaon.git.cleanRepoFromAnyFilesExceptDotGitFolder(staticPagesProjLocation);
        Helpers.writeFile([outputFromBuildAbsPath, '.nojekyll'], '');
        //#region make sure version folder are proper
        let versionFolderName = this.project.packageJson.version;
        const versionType = releaseOptions.release.overrideStaticPagesReleaseType ||
            CoreModels.ReleaseVersionTypeEnum.PATCH;
        if (versionType === CoreModels.ReleaseVersionTypeEnum.MAJOR) {
            versionFolderName = this.project.packageJson.majorVersion?.toString();
        }
        if (versionType === CoreModels.ReleaseVersionTypeEnum.MINOR) {
            versionFolderName = [
                this.project.packageJson.majorVersion?.toString(),
                this.project.packageJson.minorVersion?.toString(),
            ].join('.');
        }
        //#endregion
        const destinationStaticPagesLocationRepoAbsPath = releaseOptions.release
            .skipStaticPagesVersioning
            ? staticPagesProjLocation
            : crossPlatformPath([
                staticPagesProjLocation,
                BundledDocsFolders.VERSION,
                versionFolderName,
                architecturePrefix,
            ]);
        if (options.copyOnlyExtensions) {
            const zips = Helpers.getFilesFrom(outputFromBuildAbsPath, {
                recursive: false,
            }).filter(f => options.copyOnlyExtensions.some(ext => path.extname(f).replace('.', '') === ext.replace('.', '')));
            for (const zipFile of zips) {
                const fileName = path.basename(zipFile);
                const destZipFile = crossPlatformPath([
                    destinationStaticPagesLocationRepoAbsPath,
                    fileName,
                ]);
                HelpersTaon.copyFile(zipFile, destZipFile);
                if (await UtilsZip.splitFile7Zip(destZipFile)) {
                    Helpers.removeIfExists(destZipFile);
                }
            }
        }
        else {
            HelpersTaon.copy(outputFromBuildAbsPath, destinationStaticPagesLocationRepoAbsPath);
        }
        if (!releaseOptions.release.skipStaticPagesVersioning) {
            const versions = Helpers.foldersFrom([staticPagesProjLocation, BundledDocsFolders.VERSION], {
                recursive: false,
            });
            Helpers.writeFile([staticPagesProjLocation, BundledFiles.INDEX_HTML], `
        <html>
        <head>
          <title>Versions</title>
        </head>
        <body>
          <h1>${_.startCase(releaseOptions.release.targetArtifact)} ` +
                `versions for ${this.project.nameForNpmPackage}</h1>
          <ul>
            ${versions
                    .map(version => {
                    return (`<li><a href="${BundledDocsFolders.VERSION}/` +
                        `${path.basename(version)}${architecturePrefix ? `/${architecturePrefix}` : ''}">` +
                        `${path.basename(version)}${architecturePrefix ? `/${architecturePrefix}` : ''}</a></li>`);
                })
                    .join('')}
          </ul>

        </body>
        </html>
        `);
            UtilsTypescript.formatFile([
                staticPagesProjLocation,
                BundledFiles.INDEX_HTML,
            ]);
        }
        if (releaseOptions.website.domain && releaseOptions.website.useDomain) {
            UtilsFilesFoldersSync.writeFile([staticPagesProjLocation, BundledFiles.CNAME], releaseOptions.website.domain);
        }
        else {
            Helpers.removeFileIfExists([staticPagesProjLocation, BundledFiles.CNAME]);
        }
        if (options.createReadme) {
            Helpers.writeFile(crossPlatformPath([staticPagesProjLocation, BundledFiles.README_MD]), options.createReadme);
        }
        Helpers.info(`Static pages release done: ${staticPagesProjLocation}`);
        releaseProjPath = staticPagesProjLocation;
        if (!releaseOptions.release.skipTagGitPush) {
            projectsReposToPush.unshift(staticPagesProjLocation);
        }
        return {
            projectsReposToPush,
            releaseProjPath,
        };
        //#endregion
    }
}
//# sourceMappingURL=base-artifact.js.map