(function() {

console = function() {
    var stdout = java.lang.System.out;
    var stderr = java.lang.System.err;

    function doLog(out, type) {
        return function() {
            var args = java.lang.reflect.Array.newInstance(java.lang.Object, arguments.length - 1);
            var format = arguments[0];
            var conversionIndex = 0;
            // need to look for %d (integer) conversions because in Javascript all numbers are doubles
            for (var i = 1; i < arguments.length; i++) {
                var arg = arguments[i];
                if (conversionIndex != -1) {
                    conversionIndex = format.indexOf('%', conversionIndex);
                }
                if (conversionIndex >= 0 && conversionIndex < format.length) {
                    var conversion = format.charAt(conversionIndex + 1);
                    if (conversion === 'd' && typeof arg === 'number') {
                        arg = new java.lang.Integer(new java.lang.Double(arg).intValue());
                    }
                    conversionIndex++;
                }
                args[i-1] = arg;
            }
            try {
                out.println(type + java.lang.String.format(format, args));
            } catch(ex) {
                stderr.println(ex);
            }
        }
    }
    return {
        log: doLog(stdout, ''),
        info: doLog(stdout, 'INFO: '),
        error: doLog(stderr, 'ERROR: '),
        warn: doLog(stderr, 'WARN: ')
    };
}();

less.modules = {};

less.modules.path = {
    join: function() {
        var parts = [];
        for (i in arguments) {
            parts = parts.concat(arguments[i].split(/\/|\\/));
        }
        var result = [];
        for (i in parts) {
            var part = parts[i];
            if (part === '..' && result.length > 0) {
                result.pop();
            } else if (part === '' && result.length > 0) {
                // skip
            } else if (part !== '.') {
                if (part.slice(-1)==='\\' || part.slice(-1)==='/') {
                  part = part.slice(0, -1);
                }
                result.push(part);
            }
        }
        return result.join('/');
    },
    dirname: function(p) {
        var path = p.split('/');
        path.pop();
        return path.join('/');
    },
    basename: function(p, ext) {
        var base = p.split('/').pop();
        if (ext) {
            var index = base.lastIndexOf(ext);
            if (base.length === index + ext.length) {
                base = base.substr(0, index);
            }
        }
        return base;
    },
    extname: function(p) {
        var index = p.lastIndexOf('.');
        return index > 0 ? p.substring(index) : '';
    }
};

less.modules.fs = {
    readFileSync: function(name) {
        // read a file into a byte array
        var file = new java.io.File(name);
        var stream = new java.io.FileInputStream(file);
        var buffer = [];
        var c;
        while ((c = stream.read()) != -1) {
            buffer.push(c);
        }
        stream.close();
        return {
            length: buffer.length,
            toString: function(enc) {
                if (enc === 'base64') {
                    return encodeBase64Bytes(buffer);
                } else if (enc) {
                    return java.lang.String["(byte[],java.lang.String)"](buffer, enc);
                } else {
                    return java.lang.String["(byte[])"](buffer);
                }
            }
        };
    }
};

less.encoder = {
    encodeBase64: function(str) {
        return encodeBase64String(str);
    }
};

// ---------------------------------------------------------------------------------------------
// private helper functions
// ---------------------------------------------------------------------------------------------

function encodeBase64Bytes(bytes) {
    // requires at least a JRE Platform 6 (or JAXB 1.0 on the classpath)
    return javax.xml.bind.DatatypeConverter.printBase64Binary(bytes)
}
function encodeBase64String(str) {
    return encodeBase64Bytes(new java.lang.String(str).getBytes());
}

})();