/*
 Copyright (c) 2012, Yahoo! Inc.  All rights reserved.
 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */

function InsertionText(text, consumeBlanks) {
    this.text = text;
    this.origLength = text.length;
    this.offsets = [];
    this.consumeBlanks = consumeBlanks;
    this.startPos = this.findFirstNonBlank();
    this.endPos = this.findLastNonBlank();
}

var WHITE_RE = /[ \f\n\r\t\v\u00A0\u2028\u2029]/;

InsertionText.prototype = {

    findFirstNonBlank: function () {
        var pos = -1,
            text = this.text,
            len = text.length,
            i;
        for (i = 0; i < len; i += 1) {
            if (!text.charAt(i).match(WHITE_RE)) {
                pos = i;
                break;
            }
        }
        return pos;
    },
    findLastNonBlank: function () {
        var text = this.text,
            len = text.length,
            pos = text.length + 1,
            i;
        for (i = len - 1; i >= 0; i -= 1) {
            if (!text.charAt(i).match(WHITE_RE)) {
                pos = i;
                break;
            }
        }
        return pos;
    },
    originalLength: function () {
        return this.origLength;
    },

    insertAt: function (col, str, insertBefore, consumeBlanks) {
        consumeBlanks = typeof consumeBlanks === 'undefined' ? this.consumeBlanks : consumeBlanks;
        col = col > this.originalLength() ? this.originalLength() : col;
        col = col < 0 ? 0 : col;

        if (consumeBlanks) {
            if (col <= this.startPos) {
                col = 0;
            }
            if (col > this.endPos) {
                col = this.origLength;
            }
        }

        var len = str.length,
            offset = this.findOffset(col, len, insertBefore),
            realPos = col + offset,
            text = this.text;
        this.text = text.substring(0, realPos) + str + text.substring(realPos);
        return this;
    },

    findOffset: function (pos, len, insertBefore) {
        var offsets = this.offsets,
            offsetObj,
            cumulativeOffset = 0,
            i;

        for (i = 0; i < offsets.length; i += 1) {
            offsetObj = offsets[i];
            if (offsetObj.pos < pos || (offsetObj.pos === pos && !insertBefore)) {
                cumulativeOffset += offsetObj.len;
            }
            if (offsetObj.pos >= pos) {
                break;
            }
        }
        if (offsetObj && offsetObj.pos === pos) {
            offsetObj.len += len;
        } else {
            offsets.splice(i, 0, { pos: pos, len: len });
        }
        return cumulativeOffset;
    },

    wrap: function (startPos, startText, endPos, endText, consumeBlanks) {
        this.insertAt(startPos, startText, true, consumeBlanks);
        this.insertAt(endPos, endText, false, consumeBlanks);
        return this;
    },

    wrapLine: function (startText, endText) {
        this.wrap(0, startText, this.originalLength(), endText);
    },

    toString: function () {
        return this.text;
    }
};

module.exports = InsertionText;