"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlockStringRewriter = void 0;
const yaml_1 = require("yaml");
class BlockStringRewriter {
    constructor(indentation, maxLineLength) {
        this.indentation = indentation;
        this.maxLineLength = maxLineLength;
    }
    writeFoldedBlockScalar(node) {
        if (node.type !== 'QUOTE_DOUBLE' && node.type !== 'QUOTE_SINGLE') {
            return null;
        }
        const stringContent = node.value;
        const currentIndentNum = node.srcToken.indent;
        let indentText = this.indentation;
        for (let i = 0; i < currentIndentNum / this.indentation.length; i++) {
            indentText += this.indentation;
        }
        const lines = [];
        const splitLines = stringContent.split('\n');
        for (const line of splitLines) {
            let remainder = line;
            slicing: while (remainder.length > this.maxLineLength) {
                let location = this.maxLineLength;
                // for folded strings, space characters are placed in place of each line break
                // so we need to split the line on a space and remove the space
                while (!/ /.test(remainder.charAt(location))) {
                    location++;
                    if (location >= remainder.length) {
                        break slicing;
                    }
                }
                // however any leading space characters will be taken literally and also a newline gets inserted
                // so instead we need them to be trailing
                // which could be problematic as "trim trailing whitespace" is a common setting to have enabled but oh well
                while (/ /.test(remainder.charAt(location))) {
                    location++;
                    if (location >= remainder.length) {
                        break slicing;
                    }
                }
                const head = remainder.substring(0, location - 1 /* -1 to remove one space character, which is automatically added between lines */);
                lines.push(head);
                remainder = remainder.substring(location);
            }
            lines.push(remainder);
            lines.push('\n');
        }
        // no trailng newline
        lines.pop();
        for (let i = 1; i < lines.length;) {
            if (/^[ \t]+$/.test(lines[i])) {
                if (lines[i - 1] === '\n' || lines[i - 1] === '') {
                    lines.splice(i - 1, 1);
                    // i now points to the next entry,
                    // i - 1 points to the current entry
                    // so do not increment i
                    continue;
                }
                else {
                    // It's unconvertable, give up
                    // Explanation:
                    // If the line of text is only whitespace and it's more whitespace than the expected indentation,
                    // then it's joined with the previous line with a real newline instead of a space.
                    // This means an extra newline gets inserted if we change nothing.
                    // We can avoid this if the preceeding text is a newline,
                    // because we can just remove the preceeding newline to compensate,
                    // but if it's not we are SOL
                    return null;
                }
            }
            i++;
        }
        let blockScalarHeaderSource = '>';
        if (lines[lines.length - 1] !== '\n' && lines[lines.length - 1] !== '') {
            blockScalarHeaderSource += '-';
        }
        else if ((lines[lines.length - 2] === '\n' || lines[lines.length - 2] === '') &&
            lines[lines.length - 3] !== '\n' &&
            lines[lines.length - 3] !== '') {
            lines.splice(lines.length - 2, 2);
        }
        else {
            blockScalarHeaderSource += '+';
        }
        if (/ /.test(stringContent.charAt(0))) {
            blockScalarHeaderSource += `${indentText.length}`;
        }
        const newProps = lines.flatMap((line) => {
            if (line === '\n' || line === '') {
                // newlines can be represented as two newlines in folded blocks
                return [
                    {
                        type: 'newline',
                        indent: 0,
                        offset: node.srcToken.offset,
                        source: '\n',
                    },
                ];
            }
            return [
                {
                    type: 'newline',
                    indent: 0,
                    offset: node.srcToken.offset,
                    source: '\n',
                },
                {
                    type: 'space',
                    indent: 0,
                    offset: node.srcToken.offset,
                    source: indentText,
                },
                {
                    type: 'scalar',
                    indent: 0,
                    offset: node.srcToken.offset,
                    source: line,
                },
            ];
        });
        newProps.unshift({
            type: 'block-scalar-header',
            source: blockScalarHeaderSource,
            offset: node.srcToken.offset,
            indent: 0,
        });
        const blockString = {
            type: 'block-scalar',
            offset: node.srcToken.offset,
            indent: 0,
            source: '',
            props: newProps,
        };
        return yaml_1.CST.stringify(blockString);
    }
    writeLiteralBlockScalar(node) {
        if (node.type !== 'QUOTE_DOUBLE' && node.type !== 'QUOTE_SINGLE') {
            return null;
        }
        const stringContent = node.value;
        // I don't think it's worth it
        if (stringContent.indexOf('\n') < 0) {
            return null;
        }
        const currentIndentNum = node.srcToken.indent;
        let indentText = this.indentation;
        for (let i = 0; i < currentIndentNum / this.indentation.length; i++) {
            indentText += this.indentation;
        }
        const lines = stringContent.split('\n');
        let blockScalarHeaderSource = '|';
        if (lines[lines.length - 1] !== '\n' && lines[lines.length - 1] !== '') {
            blockScalarHeaderSource += '-';
        }
        else if (lines[lines.length - 2] !== '\n' && lines[lines.length - 2] !== '') {
            lines.splice(lines.length - 1, 1);
        }
        else {
            blockScalarHeaderSource += '+';
        }
        if (/ /.test(stringContent.charAt(0))) {
            blockScalarHeaderSource += `${indentText.length}`;
        }
        const newProps = lines.flatMap((line) => {
            if (line === '') {
                return [
                    {
                        type: 'newline',
                        indent: 0,
                        offset: node.srcToken.offset,
                        source: '\n',
                    },
                ];
            }
            return [
                {
                    type: 'newline',
                    indent: 0,
                    offset: node.srcToken.offset,
                    source: '\n',
                },
                {
                    type: 'space',
                    indent: 0,
                    offset: node.srcToken.offset,
                    source: indentText,
                },
                {
                    type: 'scalar',
                    indent: 0,
                    offset: node.srcToken.offset,
                    source: line,
                },
            ];
        });
        newProps.unshift({
            type: 'block-scalar-header',
            source: blockScalarHeaderSource,
            offset: node.srcToken.offset,
            indent: 0,
        });
        const blockString = {
            type: 'block-scalar',
            offset: node.srcToken.offset,
            indent: 0,
            source: '',
            props: newProps,
        };
        return yaml_1.CST.stringify(blockString);
    }
}
exports.BlockStringRewriter = BlockStringRewriter;
//# sourceMappingURL=block-string-rewriter.js.map