/*
  mffm Time Code
  Time Code for multimedia systems

  Copyright (C) 2000, 2001 Matt R. Flax <flatmax@ieee.org>
  
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  
  You have received a copy of the GNU Lesser General Public License
  along with this library.
*/
#ifndef MASTERCOUNTERINTERFACE_H_
#define MASTERCOUNTERINTERFACE_H_

#include <iostream>
#include "../masterCounter.H"
#include "fieldInterface.H"
#include "commonTimeCodeX.H"

//#define MSTERCOUNTERTYPE MasterCounter<FIELDTYPE, FIELDCOUNT>

template <class FIELDTYPE, int FIELDCOUNT>
class MasterCounterInterface : public MasterCounter<FIELDTYPE, FIELDCOUNT>, public HBox {
  GtkPixmap *colonGtk[FIELDCOUNT-1]; /// The colon GtkPixmaps

public:
  MasterCounterInterface(int startVal, ...) : MasterCounter<FIELDTYPE, FIELDCOUNT>(){
#if DEBUG > 1
    std::cout<<"MasterCounterInterface::MasterCounterInterface(startVal, ...)"<<std::endl;
#endif
    //Init the MasterCounter class
    va_list ap;
    va_start(ap, startVal);
    MasterCounter<FIELDTYPE, FIELDCOUNT>::init(startVal, ap);
    va_end(ap);

    //Set up the colon digits
    for (int i=0;i<FIELDCOUNT-1;i++){
      colonGtk[i]=(GtkPixmap*)gtk_pixmap_new(digitsGdk[11], digitsMasks[11]);
      if (!colonGtk[i]){
	std::cout<<"MasterCountInterface: Out of memory error"<<std::endl;
	exit(-1);
      }
      //flatmax
      gtk_object_ref(GTK_OBJECT(colonGtk[i]));
      gtk_object_sink(GTK_OBJECT(colonGtk[i]));

      gtk_widget_show(GTK_WIDGET(colonGtk[i]));
    }

    for (int i=0;i<FIELDCOUNT;i++){
      *this<<this->fields[i]->box;
      if (i!=(FIELDCOUNT-1))
	*this<<GTK_WIDGET(colonGtk[i]);
      // Reconnect the correct callbacks ...
      this->fields[i]->eventReSetup(GTK_SIGNAL_FUNC(digitPress) , this);
    }

    show();
  }

  MasterCounterInterface() : MasterCounter<FIELDTYPE, FIELDCOUNT>(){
#if DEBUG > 1
    std::cout<<"MasterCounterInterface::MasterCounterInterface()"<<std::endl;
#endif
    //Set up the colon digits
    for (int i=0;i<FIELDCOUNT-1;i++){
      colonGtk[i]=(GtkPixmap*)gtk_pixmap_new(digitsGdk[11], digitsMasks[11]);
      if (!colonGtk[i]){
	std::cout<<"MasterCountInterface: Out of memory error"<<std::endl;
	exit(-1);
      }
      //flatmax
      gtk_object_ref(GTK_OBJECT(colonGtk[i]));
      gtk_object_sink(GTK_OBJECT(colonGtk[i]));

      gtk_widget_show(GTK_WIDGET(colonGtk[i]));
    }
  }

  void init(int startVal, va_list& ap){
    //Init the MasterCounter class
    MasterCounter<FIELDTYPE, FIELDCOUNT>::init(startVal, ap);

    //    std::cout<<"MasterCounterInterface::init : event resetup"<<std::endl;
    for (int i=0;i<FIELDCOUNT;i++){
      *this<<this->fields[i]->box;
      if (i!=(FIELDCOUNT-1))
	*this<<GTK_WIDGET(colonGtk[i]);
      // Reconnect the correct callbacks ...
      this->fields[i]->eventReSetup(GTK_SIGNAL_FUNC(digitPress) , this);
    }

    show();
  }

  ~MasterCounterInterface(void){
#if DEBUG > 1
    std::cout<<"MasterCounterInterface::~MasterCounterinterface"<<std::endl;
#endif
    for (int i=0;i<FIELDCOUNT-1;i++)
      gtk_object_unref(GTK_OBJECT(colonGtk[i]));
    //    for (int i=0;i<FIELDCOUNT-1;i++)
    //  if (colonGtk[i]) gtk_widget_destroy(colonGtk[i]);
  }

  void updateMasterCount(void){
    //    std::cout <<"masterCounterInterface : updateMasterCount enter"<<std::endl;
    int activeField, carrying, requireReset=0;
    int multiplicand=1;
    count=0;
    counter tempCnt(this->getMinCount(),0,this->getMaxCount());
    for (int i=0;i<FIELDCOUNT;i++){
      activeField=FIELDCOUNT-i-1;
      tempCnt+=counter(this->getMinCount(),this->fields[activeField]->getCount()*multiplicand, this->getMaxCount());
      multiplicand*=this->fields[activeField]->getMaxCount();
      if (carrying=this->fields[activeField]->getCarry()){
	requireReset=1;
	tempCnt+=counter(this->getMinCount(), carrying*multiplicand, this->getMaxCount());
	this->fields[activeField]->resetCarry();
      }
      //std::cout<<multiplicand<<'\t';
    }
    //std::cout<<std::endl;

    count=tempCnt.getCount();
    //flatmax: might be able to remove this ...
    if (requireReset)
      this->updateFields();
  }

  static void digitPress(GtkWidget *widget, GdkEventButton *event, gpointer data){
    MasterCounterInterface *mci=(MasterCounterInterface *)data;
    int activeField;
    int howMuch=0, multiplicand=1;
    for (int i=0;i<FIELDCOUNT;i++){
      activeField=FIELDCOUNT-i-1;
      //std::cout<<"for loop enter "<<i<<std::endl;
      //      if ((howMuch=mci->fields[activeField]->digitPress(widget,event,mci->fields[activeField]))!=0)
      if ((howMuch=mci->fields[activeField]->whichDigit(widget, event->button))!=0)
	i=FIELDCOUNT; // exit early
      else
	multiplicand*=mci->fields[activeField]->getMaxCount();
      //      std::cout<<"for loop exit "<<i<<std::endl;      
    }

    //std::cout<<"multiplicand: "<<multiplicand<<std::endl;
    if (howMuch!=0)
      if (howMuch>0)
	*mci+=howMuch*multiplicand;
      else
	*mci-=-howMuch*multiplicand;
    //flatmax
    //    mci->updateFields();
  }

  void eventReSetup(GtkSignalFunc func, gpointer data){
    for (int i=0;i<FIELDCOUNT;i++)
      // Reconnect the correct callbacks ...
      this->fields[i]->FIELDTYPE::eventReSetup(func, GTK_SIGNAL_FUNC(digitPress), data, this);
  }

  // Evaluational operators
  MasterCounterInterface& operator =(counter c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator=(c);return *this;}
  MasterCounterInterface& operator =(int c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator=(c);return *this;}
  MasterCounterInterface& operator+=(counter c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator+=(c); return *this;}
  MasterCounterInterface& operator+=(int c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator+=(c); return *this;}
  MasterCounterInterface& operator-=(counter c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator-=(c); return *this;}
  MasterCounterInterface& operator-=(int c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator-=(c); return *this;}
  MasterCounterInterface& operator*=(counter c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator*=(c); return *this;}
  MasterCounterInterface& operator*=(int c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator*=(c); return *this;}
  MasterCounterInterface& operator/=(counter c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator/=(c); return *this;}
  MasterCounterInterface& operator/=(int c){MasterCounter<FIELDTYPE, FIELDCOUNT>::operator/=(c); return *this;}
};
#endif //MASTERCOUNTERINTERFACE_H_
