
import { assert } from '../../../../base/common/assert.js';
import { splitLines } from '../../../../base/common/strings.js';
import { Position } from '../position.js';
import { PositionOffsetTransformer } from './positionToOffsetImpl.js';
import { Range } from '../range.js';
import { TextLength } from './textLength.js';

class AbstractText {
    constructor() {
        this._transformer = undefined;
    }
    get endPositionExclusive() {
        return this.length.addToPosition(( new Position(1, 1)));
    }
    get lineRange() {
        return this.length.toLineRange();
    }
    getValue() {
        return this.getValueOfRange(this.length.toRange());
    }
    getValueOfOffsetRange(range) {
        return this.getValueOfRange(this.getTransformer().getRange(range));
    }
    getLineLength(lineNumber) {
        return this.getValueOfRange(( new Range(lineNumber, 1, lineNumber, Number.MAX_SAFE_INTEGER))).length;
    }
    getTransformer() {
        if (!this._transformer) {
            this._transformer = ( new PositionOffsetTransformer(this.getValue()));
        }
        return this._transformer;
    }
    getLineAt(lineNumber) {
        return this.getValueOfRange(( new Range(lineNumber, 1, lineNumber, Number.MAX_SAFE_INTEGER)));
    }
    getLines() {
        const value = this.getValue();
        return splitLines(value);
    }
    getLinesOfRange(range) {
        return range.mapToLineArray(lineNumber => this.getLineAt(lineNumber));
    }
    equals(other) {
        if (this === other) {
            return true;
        }
        return this.getValue() === other.getValue();
    }
}
class LineBasedText extends AbstractText {
    constructor(_getLineContent, _lineCount) {
        assert(_lineCount >= 1);
        super();
        this._getLineContent = _getLineContent;
        this._lineCount = _lineCount;
    }
    getValueOfRange(range) {
        if (range.startLineNumber === range.endLineNumber) {
            return this._getLineContent(range.startLineNumber).substring(range.startColumn - 1, range.endColumn - 1);
        }
        let result = this._getLineContent(range.startLineNumber).substring(range.startColumn - 1);
        for (let i = range.startLineNumber + 1; i < range.endLineNumber; i++) {
            result += '\n' + this._getLineContent(i);
        }
        result += '\n' + this._getLineContent(range.endLineNumber).substring(0, range.endColumn - 1);
        return result;
    }
    getLineLength(lineNumber) {
        return this._getLineContent(lineNumber).length;
    }
    get length() {
        const lastLine = this._getLineContent(this._lineCount);
        return ( new TextLength(this._lineCount - 1, lastLine.length));
    }
}
class ArrayText extends LineBasedText {
    constructor(lines) {
        super(lineNumber => lines[lineNumber - 1], lines.length);
    }
}
class StringText extends AbstractText {
    constructor(value) {
        super();
        this.value = value;
        this._t = ( new PositionOffsetTransformer(this.value));
    }
    getValueOfRange(range) {
        return this._t.getOffsetRange(range).substring(this.value);
    }
    get length() {
        return this._t.textLength;
    }
}

export { AbstractText, ArrayText, LineBasedText, StringText };
