var white = new Color(255, 255, 255);
var black = new Color(0, 0, 0);


// Expects 0..255 for all three parameters
function Color(r, g, b) {
  this.red = r;
  this.green = g;
  this.blue = b;
}

// 0 = no change, 1.0 = completely white
Color.prototype.lighten = function(amount) {
  return new Gradient({ '0.0': this, '1.0': white }).getColorAt(amount);
}

// 0 = no change, 1.0 = completely black
Color.prototype.darken = function(amount) {
  return new Gradient({ '0.0': this, '1.0': black }).getColorAt(amount);
}

Color.prototype.css = function() {
  return 'rgb(' + Math.round(this.red) + ',' + 
                  Math.round(this.green) + ',' + 
                  Math.round(this.blue) + ')';
}

Color.prototype.copy = function() {
  return new Color(this.red, this.green, this.blue);
}


// Expects object of form { '0.0' => Color, '0.5' => Color, '1.0' => Color }
function Gradient(stops) {
  this.stops = stops;
}

// Expects position between 0..1.
// Doesn't actually matter what the range is, though.
Gradient.prototype.getColorAt = function(position) {
  var lastStopAt = null;
  for (stopAt in this.stops) {
    if (position < stopAt) {
      if (lastStopAt == null) {
        // Before the first stop
        return this.stops[stopAt];
      } else {
        // Interpolate between two stops
        var l = this.stops[lastStopAt];
        var h = this.stops[stopAt];
        var p = (position - lastStopAt) / (stopAt - lastStopAt);
        return new Color(l.red + (h.red - l.red) * p, 
                         l.green + (h.green - l.green) * p,
                         l.blue + (h.blue - l.blue) * p);
      }
    } else {
      lastStopAt = stopAt;
    }
  }
  // After the last stop
  return this.stops[stopAt];
}