#include <qmsgbox.h>
#include <qstring.h>
#include "pbutton.h"

PipeButton::PipeButton(QWidget * parent=0,  
                       const char * name=0, 
		       const QColor fluidcol = black) : QPushButton(0,parent,name),
                       pipeline(backgroundColor()),
                       pipeback(darkGray),
                       fluid(fluidcol)
{
    
}

PipeButton::~PipeButton()
{
}


void PipeButton::drawButton( QPainter *p )
{
    QRect r = rect();                           // get rectangle

    QBrush fill(pipeback);
    QBrush fill1(backgroundColor());

    qDrawShadePanel( p, r, colorGroup(), isDown(), 1, 
                     (lt==Empty||lt==Bomb) ? &fill1 : &fill );
 
    p->setPen( QPen(pipeline,5) );                 // set fat pen
    
    drawLink(p, lt, flowDir, horzFill, vertFill);
}

void PipeButton::flow(Direction dir)
{
  bool flowOK=true;
  if(lt==Start)
    {
      if(dir==startDir)
	{
	  if(vertFill<5) horzFill=++vertFill; else emit linkFull(startDir);
	}
      else flowOK=false;
    }
  else switch(dir)
    {
    case South:
      {
	switch(lt)
	  {
	  case Cross:
	  case Down:
	    {
	      if(vertFill<10) vertFill++; else emit linkFull(South); 
	      break;
	    }

	  // Durchfluss SW
	  case Downright:
	  // Durchfluss SE
	  case Leftup:
	    {
	      // Von oben durchfliessen, also erst vertFill, dann horzFill
	      if(vertFill<5) vertFill++; else
		if(horzFill<5) horzFill++; 
		else emit linkFull(lt==Downright ? East : West);
	      break;
	    }
	  default:
	    { 
	      flowOK=false;
	      break;
	    }
	  }
	break;
      }
      case East:
	{
	  switch(lt)
	    {
	    case Cross:
	    case Right:
	      {
		if(horzFill<10) horzFill++; else emit linkFull(East); 
		break;
	      }
	    case Leftdown:
	    case Leftup:
	      {
		// EN  durchfliessen, also erst horzFill, dann vertFill
		if(horzFill<5) horzFill++; else
		  if(vertFill<5) vertFill++; 
		  else emit linkFull(lt==Leftdown? South : North); //LFEvent
		break;
	      }
	    default:
	      { 
		flowOK=false;
		break;
	      }
	    }
	  break;
	}
    case West:
      {
	switch(lt)
	  {
	  case Right:
	  case Cross:
	    {
	      if(horzFill<10) horzFill++; else emit linkFull(West); 
	      break;
	    }
	  case Upright:
	  case Downright:
	    {
	      // Von rnl  durchfliessen, also erst horzFill, dann vertFill
	      if(horzFill<5) horzFill++; else
		if(vertFill<5) vertFill++;
		else emit linkFull(lt==Upright? South : North); 
	      break;
	    }
	  default:
	    { 
	      flowOK=false;
	      break;
	    }
	  }
	break;
      }
      case North:
	{
	  switch(lt)
	    {
	    case Cross:
	    case Down:
	      {
		if(vertFill<10) vertFill++; else emit linkFull(North); 
		break;
	      }
	    case Upright:
	    case Leftdown:
	      {
		// Von unten durchfliessen, also erst vertFill, dann horzFill
		if(vertFill<5) vertFill++; else
		  if(horzFill<5) horzFill++;
		  else emit linkFull(lt==Upright? East : West); 

		break;
	      }
	    default:
	      { 
		flowOK=false;
		break;
	      }
	    }
	  break;
	}
    }
  if(flowOK)
    {
      flowDir=dir; 
      paintEvent(0);
    } else emit pipeBroken();
}
void PipeButton::drawLink(QPainter *p, LinkType l, Direction fldir, 
			  int hFill, int vFill)
{
    switch(l)
      {
	//case Start:
      case Empty:
        break;
      case Bomb:
	p->setPen(QPen(red));
	p->drawText(10,26,"Bang!",5);
	break;
      case Right:
	{
	  if(fldir==West)
	    {
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(0,SQUAREDIM/2,5*(10-hFill),SQUAREDIM/2);
	      p->setPen(QPen(fluid,5));
	      p->drawLine(5*(10-hFill),SQUAREDIM/2,SQUAREDIM,SQUAREDIM/2);
	    } else // fldir==East
	      {
		p->setPen(QPen(fluid,5));
		p->drawLine(0,SQUAREDIM/2,5*hFill,SQUAREDIM/2);
		p->setPen(QPen(pipeline,5));
		p->drawLine(5*hFill,SQUAREDIM/2,SQUAREDIM,SQUAREDIM/2);
	      }
	  break;
	}
      case Down:
	// |
	{
	  if(fldir==South)
	    {
	      p->setPen(QPen(fluid,5));
	      p->drawLine(SQUAREDIM/2,0,SQUAREDIM/2,5*vFill);
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(SQUAREDIM/2,5*vFill,SQUAREDIM/2,SQUAREDIM);
	    } else // fldir==North
	      {
		p->setPen(QPen(fluid,5));
		p->drawLine(SQUAREDIM/2,SQUAREDIM,SQUAREDIM/2,5*(10-vFill));
		p->setPen(QPen(pipeline,5));
		p->drawLine(SQUAREDIM/2,5*(10-vFill),SQUAREDIM/2,0);
	      }
	  break;
	}
      case Downright:
	{ 
	  // |
	  // --

	  // senkrechtes Stueck malen. Falls fldir South, kam
	  // die Sosse von oben reingeschwommen.

	  if(fldir==South)
	    {
	      p->setPen(QPen(fluid,5));
	      p->drawLine(SQUAREDIM/2,0,SQUAREDIM/2,5*vFill);
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(SQUAREDIM/2,5*vFill,SQUAREDIM/2,SQUAREDIM/2);
	    } else // fldir == West
	      {
		p->setPen(QPen(pipeline,5));
		p->drawLine(SQUAREDIM/2,0,SQUAREDIM/2,5*(5-vFill));
		p->setPen(QPen(fluid,5));
		p->drawLine(SQUAREDIM/2,5*(5-vFill),SQUAREDIM/2,SQUAREDIM/2);
	      }
	  
	  // waagerechtes Stueck malen. Falls fldir South, kam
	  // die Sosse von lnr  reingeschwommen.

	  if(fldir==South)
	    {
	      p->setPen(QPen(fluid,5));
	      p->drawLine(SQUAREDIM/2,SQUAREDIM/2,SQUAREDIM/2+5*hFill,
			  SQUAREDIM/2);
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(SQUAREDIM/2+5*hFill,SQUAREDIM/2,
			  SQUAREDIM,SQUAREDIM/2);
	    } else
	      {
		// Ansonsten von rechts.
		p->setPen(QPen(pipeline,5));
		p->drawLine(SQUAREDIM/2,SQUAREDIM/2,SQUAREDIM/2+5*(5-hFill),
			    SQUAREDIM/2);
		p->setPen(QPen(fluid,5));
		p->drawLine(SQUAREDIM/2+5*(5-hFill),SQUAREDIM/2,
			    SQUAREDIM,SQUAREDIM/2);
	      }
	  break;
	}
      case Leftup:
	{ 
	  //  |
	  // --

	  // senkrechtes Stueck malen. Falls fldir South, kam
	  // die Sosse von oben reingeschwommen.

	  if(fldir==South)
	    {
	      p->setPen(QPen(fluid,5));
	      p->drawLine(SQUAREDIM/2,0,SQUAREDIM/2,5*vFill);
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(SQUAREDIM/2,5*vFill,SQUAREDIM/2,SQUAREDIM/2);
	    } else // fldir == East
	      {
		p->setPen(QPen(pipeline,5));
		p->drawLine(SQUAREDIM/2,0,SQUAREDIM/2,5*(5-vFill));
		p->setPen(QPen(fluid,5));
		p->drawLine(SQUAREDIM/2,5*(5-vFill),SQUAREDIM/2,SQUAREDIM/2);
	      }
	  
	  // waagerechtes Stueck malen. Falls fldir South, kam
	  // die Sosse von rechts reingeschwommen.

	  if(fldir==South)
	    {
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(0,SQUAREDIM/2,5*(5-hFill),
			  SQUAREDIM/2);
	      p->setPen(QPen(fluid,5));
	      p->drawLine(5*(5-hFill),SQUAREDIM/2,
			  SQUAREDIM/2,SQUAREDIM/2);
	    } else // fldir == East
	      {
		// Ansonsten von links.
		p->setPen(QPen(fluid,5));
		p->drawLine(0, SQUAREDIM/2,5*hFill,
			    SQUAREDIM/2);
		p->setPen(QPen(pipeline,5));
		p->drawLine(5*hFill,SQUAREDIM/2,
			    SQUAREDIM/2,SQUAREDIM/2);
	      }

	  break;
	}
      case Upright:
	{
	  // --
	  // |

	  // senkrechtes Stueck malen. Falls fldir North, kam
	  // die Sosse von unten  reingeschwommen.

	  if(fldir==North)
	    {
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(SQUAREDIM/2,SQUAREDIM/2,SQUAREDIM/2,
			  SQUAREDIM/2+5*(5-vFill));
	      p->setPen(QPen(fluid,5));
	      p->drawLine(SQUAREDIM/2,SQUAREDIM/2+5*(5-vFill),SQUAREDIM/2,
			  SQUAREDIM);
	    } else // fldir == West
	      {
		// sonst von oben
		p->setPen(QPen(fluid,5));
		p->drawLine(SQUAREDIM/2,SQUAREDIM/2,SQUAREDIM/2,
			    SQUAREDIM/2+5*vFill);
		p->setPen(QPen(pipeline,5));
		p->drawLine(SQUAREDIM/2,SQUAREDIM/2+5*vFill,
			    SQUAREDIM/2,SQUAREDIM);
	      }
	  
	  // waagerechtes Stueck malen. Falls fldir North, kam
	  // die Sosse von links reingeschwommen.

	  if(fldir==North)  
	    {
	      p->setPen(QPen(fluid,5));
	      p->drawLine(SQUAREDIM/2,SQUAREDIM/2,SQUAREDIM/2+5*hFill,
			  SQUAREDIM/2);
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(SQUAREDIM/2+5*hFill,SQUAREDIM/2,
			  SQUAREDIM,SQUAREDIM/2);
	    } else // fldir==
	      {
		// Ansonsten von rechts.
		p->setPen(QPen(pipeline,5));
		p->drawLine(SQUAREDIM/2,SQUAREDIM/2,SQUAREDIM/2+5*(5-hFill),
			    SQUAREDIM/2);
		p->setPen(QPen(fluid,5));
		p->drawLine(SQUAREDIM/2+5*(5-hFill),SQUAREDIM/2,
			    SQUAREDIM,SQUAREDIM/2);
	      }

	  break;
	}
      case Leftdown:
	{ 
	  // --
	  //  |

	  // senkrechtes Stueck malen. Falls fldir North, kam
	  // die Sosse von unten  reingeschwommen.

	  if(fldir==North)
	    {
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(SQUAREDIM/2,SQUAREDIM/2,SQUAREDIM/2,
			  SQUAREDIM/2+5*(5-vFill));
	      p->setPen(QPen(fluid,5));
	      p->drawLine(SQUAREDIM/2,SQUAREDIM/2+5*(5-vFill),SQUAREDIM/2,
			  SQUAREDIM);
	    } else // fldir == East
	      {
		// sonst von oben
		p->setPen(QPen(fluid,5));
		p->drawLine(SQUAREDIM/2,SQUAREDIM/2,SQUAREDIM/2,
			    SQUAREDIM/2+5*vFill);
		p->setPen(QPen(pipeline,5));
		p->drawLine(SQUAREDIM/2,SQUAREDIM/2+5*vFill,
			    SQUAREDIM/2,SQUAREDIM);
	      }
	  
	  // waagerechtes Stueck malen. Falls fldir North, kam
	  // die Sosse von rechts reingeschwommen.

	  if(fldir==North)  
	    {
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(0,SQUAREDIM/2,5*(5-hFill),
			  SQUAREDIM/2);
	      p->setPen(QPen(fluid,5));
	      p->drawLine(5*(5-hFill),SQUAREDIM/2,
			  SQUAREDIM/2,SQUAREDIM/2);
	    } else // fldir==East
	      {
		// Ansonsten von links.
		p->setPen(QPen(fluid,5));
		p->drawLine(0,SQUAREDIM/2,5*hFill,
			    SQUAREDIM/2);
		p->setPen(QPen(pipeline,5));
		p->drawLine(5*hFill,SQUAREDIM/2,
			    SQUAREDIM/2,SQUAREDIM/2);
	      }

	  break;
	}
      case Cross:
	{ 
	  if(fldir==West)
	    {
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(0,SQUAREDIM/2,5*(10-hFill),SQUAREDIM/2);
	      p->setPen(QPen(fluid,5));
	      p->drawLine(5*(10-hFill),SQUAREDIM/2,SQUAREDIM,SQUAREDIM/2);
	    } else
	      {
		p->setPen(QPen(fluid,5));
		p->drawLine(0,SQUAREDIM/2,5*hFill,SQUAREDIM/2);
		p->setPen(QPen(pipeline,5));
		p->drawLine(5*hFill,SQUAREDIM/2,SQUAREDIM,SQUAREDIM/2);
	      }
	  if(fldir==South)
	    {
	      p->setPen(QPen(fluid,5));
	      p->drawLine(SQUAREDIM/2,0,SQUAREDIM/2,5*vFill);
	      p->setPen(QPen(pipeline,5));
	      p->drawLine(SQUAREDIM/2,5*vFill,SQUAREDIM/2,SQUAREDIM);
	    } else 
	      {
		p->setPen(QPen(fluid,5));
		p->drawLine(SQUAREDIM/2,SQUAREDIM,SQUAREDIM/2,5*(10-vFill));
		p->setPen(QPen(pipeline,5));
		p->drawLine(SQUAREDIM/2,5*(10-vFill),SQUAREDIM/2,0);
	      }
	  break;
	}
      case Start:
	{
	  p->setPen(QPen(pipeline,5));

	  p->drawLine(startDir==West  ? 0 : SQUAREDIM/2,
		      startDir==North ? 0 : SQUAREDIM/2, 
		      startDir==East  ? SQUAREDIM : SQUAREDIM/2,
		      startDir==South ? SQUAREDIM : SQUAREDIM/2);

	  p->setPen(QPen(fluid,5));
	  p->drawLine(startDir==West  ? 5*(5-vFill) : SQUAREDIM/2,
		      startDir==North ? 5*(5-vFill) : SQUAREDIM/2, 
		      startDir==East  ? SQUAREDIM/2+5*vFill : SQUAREDIM/2,
		      startDir==South ? SQUAREDIM/2+5*vFill : SQUAREDIM/2);
	  break;
	}
      }
}    


void PipeButton::setLink(const LinkType type) 
{ 
  lt=type;
  horzFill=vertFill=0;
  paintEvent(0);
}

void PipeButton::setFluidCol(const QColor flCol)
{
  fluid=flCol;
}



