import { Transform } from 'stream';
import { loadTemplates, createTemplateRenderer } from './template.js';
import { getFinalContext } from './context.js';
import { getFinalOptions, getGenerateOnFunction } from './options.js';
import { transformCommit } from './commit.js';
function getRequirements(context = {}, options = {}) {
    const templates = loadTemplates(options);
    const finalOptions = getFinalOptions(options, templates);
    const finalContext = getFinalContext(context, finalOptions);
    const generateOn = getGenerateOnFunction(finalContext, finalOptions);
    const renderTemplate = createTemplateRenderer(finalContext, finalOptions);
    return {
        finalContext,
        finalOptions,
        generateOn,
        renderTemplate
    };
}
export function writeChangelog(context = {}, options = {}, includeDetails = false) {
    const requirementsPromise = getRequirements(context, options);
    const prepResult = includeDetails
        ? (log, keyCommit) => ({
            log,
            keyCommit
        })
        : (log) => log;
    return async function* write(commits) {
        const { finalContext, finalOptions, generateOn, renderTemplate } = await requirementsPromise;
        const { transform, reverse, doFlush, skip } = finalOptions;
        let chunk;
        let commit;
        let keyCommit;
        let commitsGroup = [];
        let neverGenerated = true;
        let result = '';
        let savedKeyCommit = null;
        let firstRelease = true;
        for await (chunk of commits) {
            commit = await transformCommit(chunk, transform, finalContext, finalOptions);
            keyCommit = commit || chunk;
            if (skip?.(keyCommit)) {
                continue;
            }
            // previous blocks of logs
            if (reverse) {
                if (commit) {
                    commitsGroup.push(commit);
                }
                if (generateOn(keyCommit, commitsGroup)) {
                    neverGenerated = false;
                    result = await renderTemplate(commitsGroup, keyCommit, result.length > 0);
                    commitsGroup = [];
                    yield prepResult(result, keyCommit);
                }
            }
            else {
                if (generateOn(keyCommit, commitsGroup)) {
                    neverGenerated = false;
                    result = await renderTemplate(commitsGroup, savedKeyCommit, result.length > 0);
                    commitsGroup = [];
                    if (!firstRelease || doFlush) {
                        yield prepResult(result, savedKeyCommit);
                    }
                    firstRelease = false;
                    savedKeyCommit = keyCommit;
                }
                if (commit) {
                    commitsGroup.push(commit);
                }
            }
        }
        if (!doFlush && (reverse || neverGenerated)) {
            return;
        }
        result = await renderTemplate(commitsGroup, savedKeyCommit, result.length > 0);
        yield prepResult(result, savedKeyCommit);
    };
}
/**
 * Creates a transform stream which takes commits and outputs changelog entries.
 * @param context - Context for changelog template.
 * @param options - Options for changelog template.
 * @param includeDetails - Whether to emit details object instead of changelog entry.
 * @returns Transform stream which takes commits and outputs changelog entries.
 */
export function writeChangelogStream(context, options, includeDetails = false) {
    return Transform.from(writeChangelog(context, options, includeDetails));
}
/**
 * Create a changelog string from commits.
 * @param commits - Commits to generate changelog from.
 * @param context - Context for changelog template.
 * @param options - Options for changelog template.
 * @returns Changelog string.
 */
export async function writeChangelogString(commits, context, options) {
    const changelogAsyncIterable = writeChangelog(context, options)(commits);
    let changelog = '';
    let chunk;
    for await (chunk of changelogAsyncIterable) {
        changelog += chunk;
    }
    return changelog;
}
//# sourceMappingURL=data:application/json;base64,[encoded data, 4340 characters]