#include <colmask.h>
#include <config.h>
#include <defmask.h>
#include <diction.h>
#include <treectrl.h>

COLOR RGB2COLOR(unsigned char red, unsigned char green, unsigned char blue)
{
  COLOR def = XVT_MAKE_COLOR(red, green, blue);
  if (def == 0) def = COLOR_BLACK; // Per non confonderlo col colore 0, default per XI
  return def;
}

COLOR choose_color(COLOR col, WINDOW win)
{ 
  xvt_dm_post_color_sel(&col, win);
  if (col == 0) col = COLOR_BLACK; // Per non confonderlo col colore 0, default per XI
  return col;
}

COLOR blend_colors(COLOR col1, COLOR col2, double perc)
{
  const unsigned int r1 = XVT_COLOR_GET_RED(col1);
  const unsigned int g1 = XVT_COLOR_GET_GREEN(col1);
  const unsigned int b1 = XVT_COLOR_GET_BLUE(col1);
  const unsigned int r2 = XVT_COLOR_GET_RED(col2);
  const unsigned int g2 = XVT_COLOR_GET_GREEN(col2);
  const unsigned int b2 = XVT_COLOR_GET_BLUE(col2);
  const double inv_perc = 1.0 - perc;
	const byte r = byte(r1 * perc + r2*(inv_perc));
	const byte g = byte(g1 * perc + g2*(inv_perc));
	const byte b = byte(b1 * perc + b2*(inv_perc));
	return RGB2COLOR(r, g, b);
}

COLOR grayed_color(COLOR col)
{
  const unsigned int r = XVT_COLOR_GET_RED(col);
  const unsigned int g = XVT_COLOR_GET_GREEN(col);
  const unsigned int b = XVT_COLOR_GET_BLUE(col);
  const unsigned int k = (unsigned int)(0.299 * r + 0.587 * g + 0.114 * b);
  return RGB2COLOR(k, k, k);
}

///////////////////////////////////////////////////////////
// TColor_object_props
///////////////////////////////////////////////////////////

class TColor_object_props : public TObject
{         
  COLOR _back, _fore, _back_def, _fore_def;
  
public:   
  void set_back(COLOR back) { _back = back; }
  void set_fore(COLOR fore) { _fore = fore; }
  void set(COLOR back, COLOR fore) { set_back(back); set_fore(fore); }

  void set_back_def(COLOR back) { _back_def = back; }
  void set_fore_def(COLOR fore) { _fore_def = fore; }
  void set_def(COLOR back, COLOR fore) { set_back_def(back); set_fore_def(fore); }
  
  COLOR get_back() const { return _back; }
  COLOR get_fore() const { return _fore; }
  COLOR get_back_def() const { return _back_def; }
  COLOR get_fore_def() const { return _fore_def; }

  TColor_object_props(COLOR back, COLOR fore);
};

TColor_object_props::TColor_object_props(COLOR back, COLOR fore) 
                   : _back(back), _fore(fore), _back_def(back), _fore_def(fore)
{ }

///////////////////////////////////////////////////////////
// TSelect_color_mask
///////////////////////////////////////////////////////////

bool TSelect_color_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case DLG_DELREC:
    if (e == fe_button)
    {
      TProp_field& g = (TProp_field&)field(DLG_USER);
      g.freeze(true);
      TString name;
      FOR_EACH_ASSOC_OBJECT(_color_defs, h, k, o)
      {
        const TColor_object_props& p = *(const TColor_object_props*)o;
        name = k; name << "_Bg";
        g.set_property(name, p.get_back_def());
        name.rtrim(3); name << "_Fg";
        g.set_property(name, p.get_fore_def());
      }
      g.freeze(false);
      return false;
    }
    break;
  case DLG_USER:
    if (e == fe_init)
    {
      TProp_field& g = (TProp_field&)o;
      g.freeze(true);
      xvt_vobj_maximize(g.win().win());
      g.freeze(false);
    } else
    if (e == fe_close)
    {
      TProp_field& g = (TProp_field&)o;
      TString name;
      FOR_EACH_ASSOC_OBJECT(_color_defs, h, k, o)
      {
        TColor_object_props& p = *(TColor_object_props*)o;
        name = k; name << "_Bg";
        p.set_back(g.get_color_property(name));
        name.rtrim(3); name << "_Fg";
        p.set_fore(g.get_color_property(name));
      }
      save();
    }
    break;
  default: break;
  }
  return true;
}

void TSelect_color_mask::add_color(const char* key, const char* prompt, COLOR back, COLOR fore, COLOR def_back, COLOR def_fore)
{
  TString80 name = key;
  if (name.find(' ')>=0)
  {
    CHECKS(FALSE, "Lamentati con Guy se la variabile viene rifiutata ", key);
    name.strip_double_spaces();
    name.replace(' ', '_');
  }

  TProp_field& g = (TProp_field&)field(DLG_USER);

  TColor_object_props* p = (TColor_object_props*)_color_defs.objptr(name);
  if (p == NULL)
  {
    p = new TColor_object_props(def_back, def_fore);
    _color_defs.add(name, p, true);
  
    g.set_property(name, (char*)NULL, prompt); // Categoria
  }
  else
    p->set_def(back, fore);
  p->set(back, fore);

  name << "_Bg";
  g.set_property(name, back, TR("Sfondo"));  // Sfondo
  name.rtrim(3); name << "_Fg";
  g.set_property(name, fore, TR("Testo"));   // Testo
}

void TSelect_color_mask::add_color_def(const char* key, const char* prompt, COLOR def_back, COLOR def_fore)
{
  COLOR back = def_back;
  COLOR fore = def_fore;

  TConfig conf(CONFIG_GUI, _paragraph);      // Ha una possibile personalizzazione?
  conf.write_protect();
  if (!conf.new_paragraph())
  {
    TString80 name = key;
    fore = conf.get_color(name, NULL, -1, def_fore);
	  name << "_Bg";
    back = conf.get_color(name, NULL, -1, def_back);
  }

  add_color(key, prompt, back, fore, def_back, def_fore);
}   

bool TSelect_color_mask::get_color(const char* key, COLOR & back, COLOR & fore) const 
{          
  const TColor_object_props* p = (const TColor_object_props*)_color_defs.objptr(key);
  if (p != NULL)
  {
    back = p->get_back();
    fore = p->get_fore();
  }
  else
  {
    back = NORMAL_BACK_COLOR;
    fore = NORMAL_COLOR;
  }
  return p != NULL;
} 

void TSelect_color_mask::init(const char* mask_name, const char* para) 
{              
  const TFilename fn(mask_name);
  _paragraph << fn.name_only();
  if (para && *para)
    _paragraph << '_' << para;
  _paragraph.lower();
}

void TSelect_color_mask::save() const
{              
  TConfig conf(CONFIG_GUI, _paragraph);
  TString tmp;

  TAssoc_array& ass = (TAssoc_array&)_color_defs; // Fool const
  FOR_EACH_ASSOC_OBJECT(ass, h, k, o)
  {
    const TColor_object_props& p = *(const TColor_object_props*)o;
    
    tmp = k; // tmp = p.get_key(); 
    if (same_color(p.get_fore(), p.get_fore_def()))
      conf.remove(tmp);
    else
      conf.set_color(tmp, p.get_fore());

    tmp << "_Bg";
    if (same_color(p.get_back(), p.get_back_def()))
      conf.remove(tmp);
    else
      conf.set_color(tmp, p.get_back());
  }
}              

TSelect_color_mask::TSelect_color_mask(const char* mask_name, const char* para) 
                  : TAutomask("bagn007")
{              
  init(mask_name, para);
}