/*
  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 TIMECODEINTERFACE_H_
#define TIMECODEINTERFACE_H_

#include <iostream>
#include "../timeCode.H"
#include "masterCounterInterface.H"

template <class MASTERCOUNTERTYPE, class ARRAYTYPE>
class TimeCodeInterface : public TimeCode<MASTERCOUNTERTYPE, ARRAYTYPE>, public VBox {
  GtkPixmap **digitsGtk; /// The digit GtkPixmaps
  VSeparator *vsep;

  static void digitPressStart(GtkWidget *widget, GdkEventButton *event, gpointer data){
    TimeCodeInterface<MASTERCOUNTERTYPE, ARRAYTYPE> *tci=(TimeCodeInterface<MASTERCOUNTERTYPE, ARRAYTYPE>*)data;
    tci->start.digitPress(widget, event, &tci->start);
    tci->setStart(tci->start.getCount());
  }
  static void digitPress(GtkWidget *widget, GdkEventButton *event, gpointer data){
    TimeCodeInterface<MASTERCOUNTERTYPE, ARRAYTYPE> *tci=(TimeCodeInterface<MASTERCOUNTERTYPE, ARRAYTYPE>*)data;
    tci->MASTERCOUNTERTYPE::digitPress(widget, event, data);
  }
  static void digitPressEnd(GtkWidget *widget, GdkEventButton *event, gpointer data){
    TimeCodeInterface<MASTERCOUNTERTYPE, ARRAYTYPE> *tci=(TimeCodeInterface<MASTERCOUNTERTYPE, ARRAYTYPE>*)data;
    tci->end.digitPress(widget, event, &tci->end);
    tci->setEnd(tci->end.getCount());
  }
  static void digitPressWindow(GtkWidget *widget, GdkEventButton *event, gpointer data){
    TimeCodeInterface<MASTERCOUNTERTYPE, ARRAYTYPE> *tci=(TimeCodeInterface<MASTERCOUNTERTYPE, ARRAYTYPE>*)data;
    tci->window->digitPress(widget, event, tci->window);
    tci->window->updateArray();
  }

public:
  TimeCodeInterface(int startVal, ...) : TimeCode<MASTERCOUNTERTYPE, ARRAYTYPE>() {
#if DEBUG > 1
    std::cout<<"TimeCodeInterface::TimeCodeInterface(startVal, ...)"<<std::endl;
#endif
      va_list ap, ap1, ap2, ap3;
      va_start(ap, startVal);
      va_start(ap1, startVal);
      va_start(ap2, startVal);
      va_start(ap3, startVal);
      initInternal(startVal, ap, ap1, ap2, ap3);
      va_end(ap);
      va_end(ap1);
      va_end(ap2);
      va_end(ap3);
  }

  TimeCodeInterface(void) : TimeCode<MASTERCOUNTERTYPE, ARRAYTYPE>() {
#if DEBUG > 1
    std::cout<<"TimeCodeInterface::TimeCodeInterface()"<<std::endl;
#endif
  }

  void init(int c, ...){
      va_list ap, ap1, ap2, ap3;
      va_start(ap, c);
      va_start(ap1, c);
      va_start(ap2, c);
      va_start(ap3, c);
      initInternal(c, ap, ap1, ap2, ap3);
      va_end(ap);
      va_end(ap1);
      va_end(ap2);
      va_end(ap3);
  }

  void initInternal(int c, va_list& ap, va_list& apStart, va_list& apEnd, va_list& apWindow){
    TimeCode<MASTERCOUNTERTYPE, ARRAYTYPE>::init(c, ap, apStart, apEnd, apWindow);
    //Vseperators 
    if (!(vsep=new VSeparator(8)))
      std::cerr<<"TimeCodeInterface::initInternal : VSeperator malloc fail"<<std::endl;
    
    //Load the word digits ...
    //Init the Gtk pixmaps
    digitsGtk =new GtkPixmap*[4];
    if (!digitsGtk){
      std::cerr <<"TimeCodeInterface::initInternal : XPM Alloc Out of memory"<<std::endl;
      exit(-1);
    }
    for (int i=0;i<4;i++)
      digitsGtk[i]=NULL;
    
    //      int cnt=digitCnt();
    for (int i=0;i<4;i++){
      digitsGtk[i]=(GtkPixmap*)gtk_pixmap_new(digitsGdk[12+i], digitsMasks[12+i]);
      if (!digitsGtk[i]) {
	std::cerr <<"XPM Alloc 1a: Out of memory"<<std::endl;
	  exit(-1);
      }
      gtk_object_ref(GTK_OBJECT(digitsGtk[i]));
      gtk_object_sink(GTK_OBJECT(digitsGtk[i]));
      gtk_widget_show(GTK_WIDGET(digitsGtk[i]));
    }
    
    // Reconnect the correct callbacks ...
    // Start
    this->start.eventReSetup(GTK_SIGNAL_FUNC(digitPressStart), this);
    this->start<<vsep->next()<<vsep->next()<<GTK_WIDGET(digitsGtk[0]);
    // Current
    eventReSetup(GTK_SIGNAL_FUNC(digitPress), this);
    (HBox)(*this)<<vsep->next()<<vsep->next()<<GTK_WIDGET(digitsGtk[1]);
    // end
    this->end.eventReSetup(GTK_SIGNAL_FUNC(digitPressEnd), this);
    this->end<<vsep->next()<<vsep->next()<<GTK_WIDGET(digitsGtk[2]);
    // Window
    this->window->eventReSetup(GTK_SIGNAL_FUNC(digitPressWindow), this);
    (*this->window)<<vsep->next()<<vsep->next()<<GTK_WIDGET(digitsGtk[3]);

      (VBox)(*this)<<this->start.getWidget();
      (VBox)(*this)<<this->HBox::getWidget();
      (VBox)(*this)<<this->end.getWidget();

      HSeparator sep(1);
      (VBox)(*this)<<sep.grab(1);
      (VBox)(*this)<<this->window->getWidget();

      /*      Labels names; names<<"Start"<<"Current"<<"end"<<"Window Size";
      start<<names.grab(1);
      (HBox)(*this)<<names.next();
      end<<names.next();
      window<<names.next();
      */
      VBox::show();
  }

  ~TimeCodeInterface(void){
    //    VBox::hide();
#if DEBUG > 1
    std::cout<<"TimeCodeInterface::~TimeCodeInterface"<<std::endl;
#endif
    for (int i=0;i<4;i++)
      gtk_object_unref(GTK_OBJECT(digitsGtk[i]));
  }
};
#endif //TIMECODEINTERFACE_H_
