(function (tree) { // // RGB Colors - ff0014, eee // tree.Color = function (rgb, a) {

//
// The end goal here, is to parse the arguments
// into an integer triplet, such as `128, 255, 0`
//
// This facilitates operations and conversions.
//
if (Array.isArray(rgb)) {
    this.rgb = rgb;
} else if (rgb.length == 6) {
    this.rgb = rgb.match(/.{2}/g).map(function (c) {
        return parseInt(c, 16);
    });
} else {
    this.rgb = rgb.split('').map(function (c) {
        return parseInt(c + c, 16);
    });
}
this.alpha = typeof(a) === 'number' ? a : 1;

}; tree.Color.prototype = {

eval: function () { return this },

//
// If we have some transparency, the only way to represent it
// is via `rgba`. Otherwise, we use the hex representation,
// which has better compatibility with older browsers.
// Values are capped between `0` and `255`, rounded and zero-padded.
//
toCSS: function () {
    if (this.alpha < 1.0) {
        return "rgba(" + this.rgb.map(function (c) {
            return Math.round(c);
        }).concat(this.alpha).join(', ') + ")";
    } else {
        return '#' + this.rgb.map(function (i) {
            i = Math.round(i);
            i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
            return i.length === 1 ? '0' + i : i;
        }).join('');
    }
},

//
// Operations have to be done per-channel, if not,
// channels will spill onto each other. Once we have
// our result, in the form of an integer triplet,
// we create a new Color node to hold the result.
//
operate: function (op, other) {
    var result = [];

    if (! (other instanceof tree.Color)) {
        other = other.toColor();
    }

    for (var c = 0; c < 3; c++) {
        result[c] = tree.operate(op, this.rgb[c], other.rgb[c]);
    }
    return new(tree.Color)(result, this.alpha + other.alpha);
},

toHSL: function () {
    var r = this.rgb[0] / 255,
        g = this.rgb[1] / 255,
        b = this.rgb[2] / 255,
        a = this.alpha;

    var max = Math.max(r, g, b), min = Math.min(r, g, b);
    var h, s, l = (max + min) / 2, d = max - min;

    if (max === min) {
        h = s = 0;
    } else {
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);

        switch (max) {
            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
            case g: h = (b - r) / d + 2;               break;
            case b: h = (r - g) / d + 4;               break;
        }
        h /= 6;
    }
    return { h: h * 360, s: s, l: l, a: a };
},
toARGB: function () {
    var argb = [Math.round(this.alpha * 255)].concat(this.rgb);
    return '#' + argb.map(function (i) {
        i = Math.round(i);
        i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
        return i.length === 1 ? '0' + i : i;
    }).join('');
}

};

})(require('../tree'));