// -*-C++-*-
// This file is part of the gmod package
// Copyright (C) 1997 by Andrew J. Robinson

#include <stdlib.h>

#include <qpixmap.h>
#include <qpopmenu.h>

#include "defines.h"
#include "structs.h"
#include "globals.h"
#include "protos.h"

#include "Sequencer.h"

#include "CommentShell.h"
#include "OptShell.h"
#include "TopShell.h"
#include "TrackShell.h"
#include "QueueShell.h"
#include "SampleShell.h"

const char *TopShell::backXbm =
"#define backWidth 16
#define backHeight 15
static unsigned char backBits[] = {
   0x80, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc,
   0xfe, 0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0,
   0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x80};";

const char *TopShell::forwardXbm =
"#define forwardWidth 16
#define forwardHeight 15
static unsigned char forwardBits[] = {
   0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x1f, 0x3f, 0x3f,
   0x7f, 0x7f, 0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f,
   0x07, 0x07, 0x03, 0x03, 0x01, 0x01};";

const char *TopShell::previousXbm =
"#define previousWidth 18
#define previousHeight 15
static unsigned char previousBits[] = {
   0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x83, 0x83, 0x03, 0xc3, 0xc3, 0x03,
   0xe3, 0xe3, 0x03, 0xf3, 0xf3, 0x03, 0xfb, 0xfb, 0x03, 0xff, 0xff, 0x03,
   0xfb, 0xfb, 0x03, 0xf3, 0xf3, 0x03, 0xe3, 0xe3, 0x03, 0xc3, 0xc3, 0x03,
   0x83, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02};";

const char *TopShell::nextXbm =
"#define nextWidth 18
#define nextHeight 15
static unsigned char nextBits[] = {
   0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x03, 0x0f, 0x0f, 0x03,
   0x1f, 0x1f, 0x03, 0x3f, 0x3f, 0x03, 0x7f, 0x7f, 0x03, 0xff, 0xff, 0x03,
   0x7f, 0x7f, 0x03, 0x3f, 0x3f, 0x03, 0x1f, 0x1f, 0x03, 0x0f, 0x0f, 0x03,
   0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03};";

const char *TopShell::playXbm =
"#define playWidth 15
#define playHeight 15
static unsigned char playBits[] = {
  0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
  0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00,
  0x38, 0x00, 0x18, 0x00, 0x08, 0x00, };";

const char *TopShell::stopXbm =
"#define stopWidth 15
#define stopHeight 15
static unsigned char stopBits[] = {
   0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f,
   0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f,
   0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f};";

struct infoArray
{
  char *name;
  const char *pixmap;
  int size;
  int x, y, width, height;
};

TopShell::TopShell(CommentShell *commentShell, OptShell *optShell,
		   QueueShell *queueShell, SampleShell *sampleShell,
		   TrackShell *trackShell)
 : QWidget(0, "topShell"), doRandom(1)
{
  struct infoArray buttonInfo[12] = {
    {"backButton", backXbm, 272, 12, 80, 30, 30},
    {"forwButton", forwardXbm, 281, 47, 80, 30, 30},
    {"prevButton", previousXbm, 377, 83, 80, 30, 30},
    {"nextButton", nextXbm, 365, 117, 80, 30, 30},
    {"playButton", playXbm, 271, 152, 80, 30, 30},
    {"stopButton", stopXbm, 272, 187, 80, 30, 30},
    {"queueButton", "Queue", 0, 20, 115, 60, 25},
    {"optionButton", "Options", 0, 85, 115, 60, 25},
    {"trackButton", "Track", 0, 150, 115, 60, 25},
    {"sampleButton", "Samples", 0, 20, 145, 60, 25},
    {"commentButton", "Comment", 0, 85, 145, 60, 25},
    {"exitButton", "Exit", 0, 150, 145, 60, 25}
  };

  int i, j = 0;

  setCaption(HEADING);
  setMinimumSize(230, 175);
  setMaximumSize(230, 175);
  resize(230, 175);

  fileLabel = new QLabel(this, "fileLabel");
  fileLabel->setText(HEADING);
  fileLabel->setAlignment(AlignCenter);
  fileLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
  fileLabel->setGeometry(5, 5, 220, 20);

  nameLabel = new QLabel(this, "nameLabel");
  nameLabel->setText("Copyright 1997 by Andrew J Robinson");
  nameLabel->setAlignment(AlignCenter);
  nameLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
  nameLabel->setGeometry(5, 25, 220, 20);

  positionLcd = new QLCDNumber(7, this);
  positionLcd->display("EEE:000");
  positionLcd->setGeometry(12, 50, 112, 25);
  positionLcd->setFrameStyle(QFrame::Panel | QFrame::Sunken);

  channelLcd = new QLCDNumber(5, this);
  channelLcd->display("00 CH");
  channelLcd->setGeometry(136, 50, 80, 25);
  channelLcd->setFrameStyle(QFrame::Panel | QFrame::Sunken);

  for (i = 0; i < 12; i++)
    {
      button[i] = new QPushButton(this, buttonInfo[i].name);
      button[i]->setGeometry(buttonInfo[i].x, buttonInfo[i].y,
			     buttonInfo[i].width, buttonInfo[i].height);
      
      if (buttonInfo[i].size == 0)
	button[i]->setText(buttonInfo[i].pixmap);
      else
	{
	  pixmaps[j] = new QPixmap;
	  pixmaps[j]->loadFromData((const uchar *)buttonInfo[i].pixmap, buttonInfo[i].size);
	  button[i]->setPixmap(*pixmaps[j]);
	  j++;
	}
    }

  connect(button[0], SIGNAL(clicked()), this, SLOT(backClicked()));
  connect(button[1], SIGNAL(clicked()), this, SLOT(forwardClicked()));
  connect(button[2], SIGNAL(clicked()), this, SLOT(previousClicked()));
  connect(button[3], SIGNAL(clicked()), this, SLOT(nextClicked()));
  connect(button[4], SIGNAL(clicked()), this, SLOT(playClicked()));
  connect(button[5], SIGNAL(clicked()), this, SLOT(stopClicked()));
  connect(button[6], SIGNAL(clicked()), queueShell, SLOT(showQueueShell()));
  connect(button[7], SIGNAL(clicked()), optShell, SLOT(showOptShell()));
  connect(button[8], SIGNAL(clicked()), trackShell, SLOT(showTrackShell()));
  connect(button[9], SIGNAL(clicked()), sampleShell, SLOT(showSampleShell()));
  connect(button[10], SIGNAL(clicked()), commentShell, SLOT(showCommentShell()));
  connect(button[11], SIGNAL(clicked()), qApp, SLOT(quit()));
  connect(this, SIGNAL(channelSignal(int)), trackShell, SLOT(setChannels(int)));

  connect(queueShell, SIGNAL(currentDeleted()), this, SLOT(setRandom()));
}

void
TopShell::setRandom()
{
  doRandom = 1;
}

void
TopShell::setPosition(int position)
{
  char positionDisplay[8];

  if (position < 0)
    sprintf(positionDisplay, "EEE:%03d", maxPosition);
  else
    sprintf(positionDisplay, "%03d:%03d", position, maxPosition);

  positionLcd->display(positionDisplay);
}

void
TopShell::setChannels(int channels)
{
  char channelDisplay[6];

  sprintf(channelDisplay, "%02d CH", channels);
  channelLcd->display(channelDisplay);

  emit(channelSignal(channels));
}

void
TopShell::doNext(int skipError)
{
  extern Sequencer *seq;
  extern OptShell *optShell;
  extern QueueShell *queueShell;
  int startOk = 0;

  if (currentMod >= 0)
    {
      seq->stopPlayback ();
      endModule (0);

      if (optShell->removeChecked() == TRUE)
	queueShell->removeModule(currentMod);
      else
	currentMod++;
    }
  else
    currentMod = -currentMod;

  do {
    if (currentMod >= xInfo.nrFileStrings)
      currentMod = -1;

    pickRandom ();

    if (currentMod >= 0)
      {
	if (!(startOk = startPlayback (0)))
	  {
	    if (skipError)
	      queueShell->removeModule(currentMod);
	    else
	      currentMod = -currentMod - 1;
	  }
      }
  } while (skipError && !startOk && (currentMod >= 0));
}

void
TopShell::nextClicked()
{
  doNext(0);
}

void
TopShell::previousClicked()
{
  extern Sequencer *seq;
  extern OptShell *optShell;
  extern QueueShell *queueShell;

  if (currentMod >= 0)
    {
      seq->stopPlayback();
      endModule (0);
    }

  if (currentMod < 0)
    currentMod = -currentMod - 2;
  else
    {
      if (optShell->removeChecked() == TRUE)
	queueShell->removeModule(currentMod);

      if (currentMod >= 0)
	currentMod--;
    }

  pickRandom ();
  
  if (currentMod >= 0)
    if (!startPlayback (0))
      currentMod = -currentMod - 1;
}

void
TopShell::forwardClicked()
{
  extern int startPos;
  extern Sequencer *seq;

  if (currentMod >= 0)
    {
      seq->stopPlayback();
      endModule(STOP_FORWBACK);
      startPos = actualPos + 1;
      startPlayback(STOP_FORWBACK);
    }
}

void
TopShell::backClicked()
{
  extern int startPos;
  extern Sequencer *seq;

  if (currentMod >= 0)
    {
      seq->stopPlayback();
      endModule(STOP_FORWBACK);

      if (actualPos > 0)
	startPos = actualPos - 1;
      else
	startPos = 0;

      startPlayback(STOP_FORWBACK);
    }
}

void
TopShell::stopClicked()
{
  extern Sequencer *seq;

  if (currentMod >= 0)
    {
      seq->stopPlayback();
      endModule(0);
      currentMod = -currentMod - 1;
      doRandom = 0;
    }
}

void
TopShell::playClicked()
{
  extern Sequencer *seq;
  
  if (currentMod < 0)
    {
      currentMod = -currentMod - 1;

      if (doRandom)
	{
	  pickRandom();
	  doRandom = 0;
	}
      
      if (currentMod >= xInfo.nrFileStrings)
	currentMod = -1;
    }
  else
    {
      seq->stopPlayback();
      endModule(0);
    }

  if (currentMod >= 0)
    if (!startPlayback (0))
      currentMod = -currentMod - 1;
}

void
TopShell::pickRandom(void)
{
  extern OptShell *optShell;

  if (xInfo.nrFileStrings > 0)
    {
      if (optShell->randomChecked() == TRUE)
	currentMod = rand () % xInfo.nrFileStrings;
    }
}

#ifndef DEPEND
#include "TopShell.moc"
#endif
