#include <colors.h>
#include <varmask.h>

#include "cg2102.h"

///////////////////////////////////////////////////////////
// Maschere per colori
///////////////////////////////////////////////////////////

class TRow_mask : public TMask
{ 
public:
  virtual void update();

  TRow_mask();
  virtual ~TRow_mask() { }
};

class TColor_mask : public TVariable_mask
{        
  HIDDEN TRow_mask* _sheet_mask;
  HIDDEN TMask* get_mask(int, TMask&) { return _sheet_mask; }

protected:
  static bool color_handler(TMask_field& f, KEY k);
  
public:
  void get_cur_colors(COLOR& back, COLOR& fore) const;  
  void set_cur_colors(COLOR back, COLOR fore); 

  TColor_mask();
  virtual ~TColor_mask();
};

///////////////////////////////////////////////////////////
// TRow_mask
///////////////////////////////////////////////////////////

TRow_mask* TColor_mask::_sheet_mask = NULL;

TRow_mask::TRow_mask()
         : TMask("cg2100k", 1)
{
}

void TRow_mask::update()
{               
  TSheet_field* s = get_sheet();
  TColor_mask& m = (TColor_mask&)s->mask();
  COLOR back, fore;
  m.get_cur_colors(back, fore);
  
  set_pen(COLOR_BLACK);
  set_brush(back);
  frame(2, 4, 16, 6, 0);
  set_brush(fore);
  frame(20, 4, 34, 6, 0);
}

///////////////////////////////////////////////////////////
// TColor_mask
///////////////////////////////////////////////////////////


void TColor_mask::get_cur_colors(COLOR& back, COLOR& fore) const
{
  TSheet_field& s = (TSheet_field&)fld(0);
  TToken_string& row = s.row(s.selected());
  const char tipo = row.right(1)[0];
  app().type2colors(tipo, back, fore);
}

void TColor_mask::set_cur_colors(COLOR back, COLOR fore)
{
  TSheet_field& s = (TSheet_field&)fld(0);
  TToken_string& row = s.row(s.selected());
  const char tipo = row.right(1)[0];
  app().set_type_colors(tipo, back, fore);
  s.set_back_and_fore_color(back, fore, s.selected()); 
}
  
bool TColor_mask::color_handler(TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {                                               
    TMask& m = f.mask();
    TColor_mask& cm = (TColor_mask&)m.get_sheet()->mask();
    
    COLOR back, fore;
    cm.get_cur_colors(back, fore);     
    const bool use_back = f.dlg() == 100;
    
    const COLOR col = choose_color(use_back ? back : fore, m.win());
    if (col != COLOR_INVALID)
    {                   
      if (use_back)
        back = col;
      else
        fore = col;  
      cm.set_cur_colors(back, fore);
      cm._sheet_mask->update();
    }  
  }
  return TRUE;
}

TColor_mask::TColor_mask() 
           : TVariable_mask("cg2100k")
{              
  CHECK(_sheet_mask == NULL, "One color at time, please");
  _sheet_mask = new TRow_mask;
  _sheet_mask->set_handler(99, color_handler);
  _sheet_mask->set_handler(100, color_handler);

  TVariable_sheet_field& s = (TVariable_sheet_field&)fld(0);
  s.set_getmask(get_mask);

  const char* const tipi = "TFSIDNAPRC"; 
  TPrimanota_application& a = app();
  
  int row = 0;
  for (const char* c = tipi; *c; c++)
  {
    COLOR back, fore;
    a.type2colors(*c, back, fore);
    TToken_string& riga = s.row(-1);
    riga << "Riga " << *c;
    s.set_back_and_fore_color(back, fore, row++); 
  }
}

TColor_mask::~TColor_mask() 
{
  delete _sheet_mask;
  _sheet_mask = NULL;
}


///////////////////////////////////////////////////////////
// Gestione righe colorate
///////////////////////////////////////////////////////////

void TPrimanota_application::load_colors()
{
  TConfig conf(CONFIG_USER, "cg2");
  TAssoc_array& colori = (TAssoc_array&)conf.list_variables();
  for (THash_object* o = colori.get_hashobj(); o; o = colori.get_hashobj())
  {
    const TString& key = o->key();
    if (key.len() == 7 && key.compare("Color", 5, TRUE) == 0)
    {
      const COLOR col = conf.get_color(key);
      TString* strcol = new TString(15);
      strcol->format("%ld", col);
      _colori.add(key.mid(5), strcol);
    }  
  }
}              

void TPrimanota_application::save_colors()
{
  TConfig conf(CONFIG_USER, "cg2");
  TString16 tmp;
  for (THash_object* o = _colori.get_hashobj(); o; o = _colori.get_hashobj())
  {
    tmp = "Color"; tmp << o->key();
    const COLOR col = atol((TString&)o->obj());
    
    bool should_delete = FALSE;
    if (tmp[5] == 'B')
      should_delete = (col == NORMAL_BACK_COLOR);
    else  
      should_delete = (col == NORMAL_COLOR);
    
    if (should_delete)  
      conf.remove(tmp);
    else  
      conf.set_color(tmp, col);
  }
}              

COLOR TPrimanota_application::type2color(char tipor, char tipoc)
{  
  COLOR col;                         
  if (tipor > ' ')
  {
    const char key[3] = { tipoc, tipor, '\0' }; 
    TString* colstr = (TString*)_colori.objptr(key);
    if (colstr == NULL)
    {
      colstr = new TString(8);
      colstr->format("%ld", tipoc == 'B' ? NORMAL_BACK_COLOR : NORMAL_COLOR);
      _colori.add(key, colstr);
    }    
    col = atol(*colstr);
  }  
  else
  {
    col = tipoc == 'B' ? NORMAL_BACK_COLOR : NORMAL_COLOR;
  }
  return col;
}

void TPrimanota_application::set_type_color(char tipor, char tipoc, COLOR col)
{ 
  if (tipor > ' ')
  {
    const char key[3] = { tipoc, tipor, '\0' }; 
    TString* colstr = (TString*)_colori.objptr(key);
    if (colstr == NULL)
    {
      colstr = new TString(8);
      _colori.add(key, colstr);
    }
    colstr->format("%ld", col);
  }  
}

void TPrimanota_application::type2colors(char tipor, COLOR& back, COLOR& fore)
{      
  back = type2color(tipor, 'B');
  fore = type2color(tipor, 'F');
}

void TPrimanota_application::set_type_colors(char tipor, COLOR back, COLOR fore)
{      
  set_type_color(tipor, 'B', back);
  set_type_color(tipor, 'F', fore);
}

void TPrimanota_application::set_colors()
{
  TColor_mask colors;
  if (colors.run() == K_ENTER)
    app().save_colors();
  else
    app().load_colors();
} 

///////////////////////////////////////////////////////////
// Gestione cambiamento prorata
///////////////////////////////////////////////////////////

#include <rmov.h>
#include <rmoviva.h>

bool TPrimanota_application::test_prorata()
{
  if (iva() != iva_acquisti)
    return TRUE;
  
  bool esistono_righe_senza_tipo_detrazione = FALSE;
  
  TString_array& righe_iva = ivas().rows_array();
  for (int r = 0; r < righe_iva.items(); r++)
  {
    TToken_string& row = righe_iva.row(r);       
    if (!row.empty_items())
    {
      const int tipodet = row.get_int(2);
      if (tipodet == 0)
      {
        esistono_righe_senza_tipo_detrazione = TRUE;
        break;
      }  
    }  
    else
      break;
  }
  
  bool ok = TRUE;                       
  if (esistono_righe_senza_tipo_detrazione)
  {
    const bool prorata100 = causale().reg().prorata() >= 100.0;
    const bool esistono_righe_iva_detraibile = type2pos('D') >= 0;
    
    if (prorata100)
      ok = !esistono_righe_iva_detraibile;
    else
      ok = esistono_righe_iva_detraibile;
  }
  
  return ok;  
}

bool TPrimanota_application::aggiusta_prorata()
{
  if (test_prorata())
    return FALSE;
    
  begin_wait();
  
  TRegistro& reg = causale().reg();
  const real prorata_attuale = reg.prorata();
  const real vecchio_prorata = prorata_attuale < 100.0 ? 100.0 : 0.0;    
  
  TSheet_field& iva_sheet = ivas();
  TString_array& righe_iva = iva_sheet.rows_array();
    
  TToken_string oldrow(128);
  for (int i = 0; i < righe_iva.items(); i++)
  {
    TToken_string& r = righe_iva.row(i);
    if (!r.empty_items())
    {
      oldrow = r;                          // Memorizza riga iva
      reg.set_prorata(vecchio_prorata);
      iva_notify(iva_sheet, i, K_SPACE);   
      r.add("", 0); r.add("", 3);          // Simula l'azzeramento degli importi
      iva_notify(iva_sheet, i, K_ENTER);   // Simula uscita dalla riga

      reg.set_prorata(prorata_attuale);
      iva_notify(iva_sheet, i, K_SPACE);   
      r = oldrow;                          // Simula riscrittura importi
      iva_notify(iva_sheet, i, K_ENTER);   // Simula uscita dalla riga
    }
    else
      break;
  }
  
  end_wait(); 
  return TRUE;
} 

bool TPrimanota_application::prorata_handler(TMask_field& f, KEY k)
{
  if (k == K_SPACE)
  {
    if (app().aggiusta_prorata())
      f.hide();
  }
  
  return TRUE;
}
