// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.

#ifndef tools_hls
#define tools_hls

namespace tools {

//T is float or double.

template <class T>
inline T hls_to_rgb2(T rn1,T rn2,T huei) {
  // taken from CERN-ROOT/TColor.
  T hue = huei;
  if (hue > 360) hue = hue - 360;
  if (hue < 0)   hue = hue + 360;
  if (hue < 60 ) return rn1 + (rn2-rn1)*hue/60;
  if (hue < 180) return rn2;
  if (hue < 240) return rn1 + (rn2-rn1)*(240-hue)/60;
  return rn1;
}

template <class T>
inline void hls_to_rgb(T hue,T light,T satur,T& a_r,T& a_g,T& a_b){
  // taken from CERN-ROOT/TColor.
  // Static method to compute RGB from HLS. The l and s are between [0,1]
  // and h is between [0,360]. The returned r,g,b triplet is between [0,1].

  T rh, rl, rs, rm1, rm2;
  rh = rl = rs = 0;

  if (hue   > 0) rh = hue;
  if (rh > 360) rh = 360;

  if (light > 0) rl = light;
  if (rl > 1)   rl = 1;

  if (satur > 0) rs = satur;
  if (rs > 1)   rs = 1;

  if (rl <= T(0.5)) {
    rm2 = rl*(1 + rs);
  } else {
    rm2 = rl + rs - rl*rs;
  }
  rm1 = 2*rl - rm2;

  if (!rs) { a_r = rl; a_g = rl; a_b = rl; return; }
  a_r = hls_to_rgb2(rm1, rm2, rh+120);
  a_g = hls_to_rgb2(rm1, rm2, rh);
  a_b = hls_to_rgb2(rm1, rm2, rh-120);
}

template <class T>
inline void rgb_to_hls(T rr,T gg,T bb,T& hue,T& light,T& satur) {
  // The r,g,b triplet is between
  // [0,1], hue is between [0,360], light and satur are [0,1].

  T rnorm, gnorm, bnorm, minval, maxval, msum, mdiff, cr, cg, cb;
  minval = maxval = 0;
  cr = cg = cb = 0;

  if (rr > 0) cr = rr;
  if (cr > 1) cr = 1;

  if (gg > 0) cg = gg;
  if (cg > 1) cg = 1;

  if (bb > 0) cb = bb;
  if (cb > 1) cb = 1;

  minval = cr;
  if (cg < minval) minval = cg;
  if (cb < minval) minval = cb;
  maxval = cr;
  if (cg > maxval) maxval = cg;
  if (cb > maxval) maxval = cb;

  rnorm = gnorm = bnorm = 0;
  mdiff = maxval - minval;
  msum  = maxval + minval;
  light = T(0.5) * msum;
  if (maxval != minval) {
    rnorm = (maxval - cr)/mdiff;
    gnorm = (maxval - cg)/mdiff;
    bnorm = (maxval - cb)/mdiff;
  } else {
    satur = hue = 0;
    return;
  }

  if (light < T(0.5))
    satur = mdiff/msum;
  else
    satur = mdiff/(2 - msum);

  if (cr == maxval)
    hue = 60 * (6 + bnorm - gnorm);
  else if (cg == maxval)
    hue = 60 * (2 + rnorm - bnorm);
  else
    hue = 60 * (4 + gnorm - rnorm);

  if (hue > 360)
    hue = hue - 360;
}


}

#endif
