/*
Copyright 2009 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// TODO: If Flash code is modified to use GradientControl
// (http://gmaps-utility-library-flash.googlecode.com/svn/trunk/examples/GradientControl/bin-release/index.html), this file will become unnecessary.

/**
 * Define a linear transform using two numerical ranges.
 * Given a number from the source range, calculate the corresponding
 * number in the destination range.
 * @param {object} srcDict Object with source range boundaries.
 * @param {object} dstDict Object with destination range boundaries.
 * @param {number} src Number to scale.
 * @param {array} dstPointCount Optionally divide the result range
 *   into discrete points and snap the result to one of them.
 * @return {number} A number from within the destination range.
 */
function linearGradient(srcDict, dstDict, src, dstPointCount) {
  var minSrc = srcDict['min'];
  var maxSrc = srcDict['max'];
  var minDst = dstDict['min'];
  var maxDst = dstDict['max'];

  var srcNorm = src;
  var dst;
  if (minSrc == maxSrc) {
    dst = minDst;
  } else {
    dst = Math.round((minDst + ((srcNorm - minSrc) / (maxSrc - minSrc) * (maxDst - minDst)))*100)/100;
  }
  var result;
  if (minDst < maxDst) {
    result = Math.min(Math.max(minDst, dst), maxDst);
  } else {
    result = Math.max(Math.min(minDst, dst), maxDst);
  }
  if (typeof(dstPointCount) != 'undefined') {
    var step = (maxDst - minDst) / (dstPointCount + 0.0);
    var stepNum = linearGradient(
        dstDict, {'min': 0, 'max': dstPointCount}, result);
    result = minDst + stepNum * step;
  }
  return result;
}


/**
 * Define a linear transform from a numerical range to a color range.
 * Given a number from the source range, calculate the corresponding
 * number in the color range.
 * @param {object} srcDict Object with source range boundaries.
 * @param {object} dstColorDict Object with destination color range boundaries.
 * @param {number} src Number to scale.
 * @param {array} dstPointCount Optionally divide the result range
 *   into discrete points and snap the result to one of them.
 * @return {number} A color from within the destination range.
 */
function colorGradient(srcDict, dstColorDict, src, dstPointCount) {
  var colors = [];
  for (var i = 0; i < dstColorDict['max'].length; i++) {
    colors.push({'min': dstColorDict['min'][i], 'max': dstColorDict['max'][i]});
  }
  r = linearGradient(srcDict, colors[0], src, dstPointCount)
  g = linearGradient(srcDict, colors[1], src, dstPointCount)
  b = linearGradient(srcDict, colors[2], src, dstPointCount)
  return sprintf('%02x%02x%02x', b, g, r);
}

/**
 * Define a linear transform from a numerical ranges to one of a number
 * of color ranges. Given a number from the source range, choose one
 * of the color ranges and perform linear scaling within it.
 * @param {array} gradientList Array of objects, each defining a single
 *   gradient range.
 * @param {number} src Number to scale.
 * @param {array} dstPointCount Optionally divide the result range
 *   into discrete points and snap the result to one of them.
 * @return {number} A color from within one of the destination ranges.
 */
function multiColorGradient(gradientList, src, dstPointCount) {
  var listLength = gradientList.length;

  for (var i = 0; i < listLength; i++) {
    var gradient = gradientList[i];
    if (src <= gradient.maxValue) {
      return colorGradient(
        {'min': gradient.minValue, 'max': gradient.maxValue},
        {'min': gradient.minColor, 'max': gradient.maxColor},
        src, dstPointCount)
    }
  }
}

