// lz77.js
// https://github.com/gnh1201/welsonjs

function compress(input) {
    var compressed = '';
    var searchBufferIndex = 0;

    while (searchBufferIndex < input.length) {
        var longestMatchLength = 0;
        var longestMatchOffset = 0;

        // Search for the longest match in the look-ahead buffer
        for (var i = 0; i < searchBufferIndex; i++) {
            var matchLength = 0;
            while (matchLength < input.length - searchBufferIndex && input.charAt(i + matchLength) === input.charAt(searchBufferIndex + matchLength)) {
                matchLength++;
            }

            if (matchLength > longestMatchLength) {
                longestMatchLength = matchLength;
                longestMatchOffset = searchBufferIndex - i;
            }
        }

        // Output the token (offset, length)
        if (longestMatchLength > 0) {
            compressed += '(' + longestMatchOffset + ',' + longestMatchLength + ')';
            searchBufferIndex += longestMatchLength;
        } else {
            compressed += '(0,' + input.charAt(searchBufferIndex) + ')';
            searchBufferIndex++;
        }
    }

    return compressed;
}

function decompress(compressedData) {
    var decompressed = '';
    var currentIndex = 0;

    while (currentIndex < compressedData.length) {
        if (compressedData.charAt(currentIndex) === '(') {
            // Match case
            var commaIndex = compressedData.indexOf(',', currentIndex);
            var offset = parseInt(compressedData.substring(currentIndex + 1, commaIndex), 10);
            var closingParenIndex = compressedData.indexOf(')', commaIndex);
            var length = parseInt(compressedData.substring(commaIndex + 1, closingParenIndex), 10);

            for (var i = 0; i < length; i++) {
                var copyIndex = decompressed.length - offset;
                decompressed += decompressed.charAt(copyIndex);
            }

            currentIndex = closingParenIndex + 1;
        } else {
            // Literal case
            decompressed += compressedData.charAt(currentIndex);
            currentIndex++;
        }
    }

    return decompressed;
}

exports.compress = compress;
exports.decompress = decompress;

exports.VERSIONINFO = "LZ77 (MsCompress) algorithm implementation version 0.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;