/** 
  \class CCodecFrame
  \brief A base class for video codecs
  
 */

#include <stdio.h>

#include "CamStreamApp.h"
#include "CodecFrame.h"

CCodecFrame::CCodecFrame(QWidget *parent, const char *name)
	: CCamFrame(parent, name)
{
   /* Create and initialize dialog */
   pPanels = new CPanelSelector();
   connect(pPanels, SIGNAL(Closed()), this, SLOT(PanelsDlgClosed()));
}

CCodecFrame::~CCodecFrame()
{
   printf("Panels remaining: %d\n", PanelList.count());
}

// private


/* Adjust sizes of just about everything... Also sets calc[] parameters */
void CCodecFrame::RecalculateSize()
{
   int boxes;
   int x, y, liney, tx, ty;
   int swidth, sheight;
   QString size_text;
   QSize sz;

   QListIterator<CCamPanel> *cit;
   CCamPanel *pit;

   /* Determine size, based on the number of visible panels. We walk the
      list of panels, and place panels next to each other, but not with
      more than 4 panels on a row.
    */
   tx = GetViewPort().left();
   ty = GetViewPort().top();

   x = y = liney = swidth = sheight = 0;
   cit = new QListIterator<CCamPanel>(PanelList);
   while ((pit = cit->current())) {
      // Update storage of visibility
      CamApp->SetPanelVisibility(pit->GetName(), pit->IsVisible());

      if (pit->IsVisible()) {
        sz = pit->GetVisibleSize();
printf("Repositioning panel %s to (%d, %d), visible size = %dx%d\n", (const char *)pit->GetName(), x, y, sz.width(), sz.height());
        pit->location.moveTopLeft(QPoint(tx + x, ty + y));
        x += sz.width();

        // Update height of this row 
        if (sz.height() > liney)
          liney = sz.height();

        // Update width and height of total of panels
        if (x > swidth)
          swidth = x;
        if (y + liney > sheight)
          sheight = y + liney;

        boxes++;
        if ((boxes & 3) == 0) {
          // New row
          x = 0;
          y += liney;
          liney = 0;
        }
      }
#if 0
      else
        printf("Panel %s is hidden\n", (const char *)pit->GetName());
#endif             
      ++*cit;
   }
   delete cit;

   SetViewPort(QSize(swidth, sheight));   
}

// protected

/**
  \fn void CCodecFrame::drawContents(QPainter *p)
  \brief Draws all visible panels.
*/
void CCodecFrame::drawContents(QPainter *p)
{
   QListIterator<CCamPanel> *cit;
   CCamPanel *pit;

   cit = new QListIterator<CCamPanel>(PanelList);
   while ((pit = cit->current())) {
      if (pit->IsVisible())
        pit->Draw(p);
      ++*cit;
   }
   delete cit;
}

void CCodecFrame::mousePressEvent(QMouseEvent *me)
{
   // See if we overlap any of the panels
   QListIterator<CCamPanel> *cit;
   CCamPanel *pit;
   QPoint mp;
   
   mp = me->pos();
   cit = new QListIterator<CCamPanel>(PanelList);
   while ((pit = cit->current())) {
      if (pit->IsVisible() && pit->location.contains(mp))
        pit->RightClick(me->globalPos());
      ++*cit;
   }
   delete cit;
}

/** 
  \fn void CCodecFrame::RegisterPanel(CCamPanel *p)
  \brief Add a panel to the list of known panels,
  \param p Pointer to \ref CCamPanel class.
  
  This function adds the CCamPanel p to the list of known panels. It also
  sets the visibility, as registered in CCamStreamApp.
 */
void CCodecFrame::RegisterPanel(CCamPanel *p)
{
   const char *n, *d;
   QSize sz;
   bool is_vis;
   
   n = p->GetName();
   d = p->GetDescription();
   sz = p->GetVisibleSize();
#if TRACE_PANELREG
   printf("Registering panel %s (%s), visible size %dx%d\n", n, d, sz.width(), sz.height());
#endif   
   PanelIdx.replace(n, p);
   if (p->IsDrawable()) {
     PanelList.append(p);
     pPanels->AddPanel(p);
     connect(p, SIGNAL(ChangedVisibility(bool)), this, SLOT(PanelOnOff(bool)));
     connect(p, SIGNAL(ChangedVisibleSize(const QSize &)), this, SLOT(PanelChangedSize(const QSize &)));
   }
   
   is_vis = CamApp->GetPanelVisibility(p->GetName());
   p->SetVisibility(is_vis);
}

/**
  \fn void CCodecFrame::UnregisterPanel(CCamPanel *p, bool Delete = FALSE)
  \brief Remove panel from list of known panels.
  \param p The \ref CCamPanel to remove.
  \param Delete When TRUE, will also delete the object
  
  This function removes the object from the list of available 
  (and drawable) panels. When asked to it will also destroy the object.
*/
void CCodecFrame::UnregisterPanel(CCamPanel *p, bool Delete)
{
#if TRACE_PANELREG
   printf("Unregistering panel %s (%s)\n", (const char *)p->GetName(), (const char *)p->GetDescription());
#endif
   PanelIdx.remove(p->GetName());
   if (p->IsDrawable()) {
     PanelList.remove(p);
     //pPanels->RemovePanel(p);
   }
   if (Delete)
     delete p;
}


/**
  \fn CCamPanel *CCodecFrame::GetPanel(const char *name) const
  \brief Find a panel in the list of known panels
  \param name The name of the panel.
  \return A \ref CCamPanel object, or NULL if the panel could not be found.
*/

CCamPanel *CCodecFrame::GetPanel(const char *name) const
{
   CCamPanel *pret = NULL;
   
   pret = PanelIdx[name];
   return pret;
}

// protected slots

void CCodecFrame::TogglePanelsDlg(bool isOn)
{
   if (isOn)
     pPanels->show();
   else
     pPanels->hide();
}


void CCodecFrame::PanelsDlgClosed()
{
   pPanels->hide();
   // button?
}

/**
  
  Should be called when a Panel is changed, for example its size or 
  visability.
*/
void CCodecFrame::UpdatePanelView()
{
   RecalculateSize();
   pPanels->CheckBoxes();
}
   

// public

