/***************************************************************************
                          pipequeue.cpp  -  description
                             -------------------
    begin                : Sat Sep 30 2000
    copyright            : (C) 2000 by Waldemar Baraldi
    email                : baraldi@lacasilla.com.ar
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "pipequeue.h"
#include "cross.h"
#include "horizontal.h"
#include "vertical.h"
#include "elbowupright.h"
#include "elbowdownright.h"
#include "elbowupleft.h"
#include "elbowdownleft.h"
#include "horizontalbowl.h"
#include "verticalbowl.h"
#include "random.h"

PipeQueue::PipeQueue():AnimatedCanvas(){
  index=0;
  change=true;
  res_coef=0;
  fixed_coef=0;
  filled=false;
}

PipeQueue::~PipeQueue(){
  if (filled)
    for (int i=0;i<MaxPipes;i++)
      delete queue[i];
}

int PipeQueue::width(){
  return PipeWidth;
}

int PipeQueue::height(){
  return PipeHeight;
}

Pipe * PipeQueue::getPipe(int pos){
  change=true;
  if (!filled) fillUp();
  return queue[(pos+index)%MaxPipes];
}

Pipe * PipeQueue::getHead(){
  if (!filled) fillUp();

  Pipe * aux=queue[index];
  queue[index]=generatePipe();
  index=(index+1)% MaxPipes;
  change=true;
  return aux;
}

void PipeQueue::setRestrictionCoef(unsigned int coef){
  if (coef > 100)
    res_coef=100;
  else res_coef=coef;
}

void PipeQueue::setFixedCoef(unsigned int coef){
  if (coef > 100)
    fixed_coef=100;
  else fixed_coef=coef;

}

bool PipeQueue::isChanged(){
  return change;
}

void PipeQueue::fillUp(){
  for (index=0;index<MaxPipes;index++)
    queue[index]=generatePipe();
  index=0;
  change=true;
  filled=true;
}

void PipeQueue::paint(VideoManager * vm){
  if (change){
    int i,j;
    Image * ima=vm->getImageManager()->getImage(new Str("queue_one.png"));
    vm->blit(ima, x,y);

  //Pintar los pipes
    j=index;
    for (i=0;i<MaxPipes;i++){
      j=(j+MaxPipes -1)% MaxPipes;
      queue[j]->setPos(x+27, y+5+i*queue[j]->height());
      queue[j]->paint(vm);
    }
  }
  change=false;
}

Pipe * PipeQueue::generatePipe(){

 Pipe * aux=NULL;
 Random * r=new Random();
 switch ((r->getRandomNumber(0, 6))){

   case 0: {
     aux=new Cross();
     if ((unsigned int)r->getRandomNumber(1,100)<=fixed_coef)
       aux->setFixed(true);
     for (int i=0;i<2;i++)
       if ((unsigned int)r->getRandomNumber(1,100)<=res_coef)
         switch (r->getRandomNumber(0, 3)){
           case 0:{
             if (!aux->isRestrictedAsOutput(South))
               aux->restrictAsOutput(North);
             break;
           }
           case 1:{
             if (!aux->isRestrictedAsOutput(North))
               aux->restrictAsOutput(South);
             break;
           }
           case 2:{
             if (!aux->isRestrictedAsOutput(East))
               aux->restrictAsOutput(West);
             break;
           }
           case 3:{
             if (!aux->isRestrictedAsOutput(West))
               aux->restrictAsOutput(East);
             break;
           }
           default:break;
         }
     break;
   }
   case 1: {
    if ((unsigned int)r->getRandomNumber(0,3))
      aux=new Horizontal();
    else aux= new HorizontalBowl();
    if ((unsigned int)r->getRandomNumber(1,100)<=fixed_coef)
       aux->setFixed(true);
    if ((unsigned int)r->getRandomNumber(1,100)<=res_coef)
      switch (r->getRandomNumber(0, 1)){
        case 0:{
          aux->restrictAsOutput(West);
          break;
        }
        case 1:{
          aux->restrictAsOutput(East);
          break;
        }
        default:break;
      }
     break;
   }
   case 2: {
    if ((unsigned int)r->getRandomNumber(0,3))
      aux= new Vertical();
    else aux= new VerticalBowl();
    if ((unsigned int)r->getRandomNumber(1,100)<=fixed_coef)
       aux->setFixed(true);
    if ((unsigned int)r->getRandomNumber(1,100)<=res_coef)
      switch (r->getRandomNumber(0, 1)){
        case 0:{
          aux->restrictAsOutput(North);
          break;
        }
        case 1:{
          aux->restrictAsOutput(South);
          break;
        }
        default:break;
      }
     break;
   }
   case 3: {
     aux= new ElbowUpRight();
     if ((unsigned int)r->getRandomNumber(1,100)<=fixed_coef)
       aux->setFixed(true);
     if ((unsigned int)r->getRandomNumber(1,100)<=res_coef)
       switch (r->getRandomNumber(0, 1)){
         case 0:{
           aux->restrictAsOutput(North);
           break;
         }
         case 1:{
           aux->restrictAsOutput(East);
           break;
         }
         default:break;
       }
     break;
   }
   case 4: {
     aux= new ElbowUpLeft();
     if ((unsigned int)r->getRandomNumber(1,100)<=fixed_coef)
       aux->setFixed(true);
     if ((unsigned int)r->getRandomNumber(1,100)<=res_coef)
       switch (r->getRandomNumber(0, 1)){
         case 0:{
           aux->restrictAsOutput(North);
           break;
         }
         case 1:{
           aux->restrictAsOutput(West);
           break;
         }
         default:break;
       }
     break;
   }
   case 5: {
     aux= new ElbowDownRight();
     if ((unsigned int)r->getRandomNumber(1,100)<=fixed_coef)
       aux->setFixed(true);
     if ((unsigned int)r->getRandomNumber(1,100)<=res_coef)
       switch (r->getRandomNumber(0, 1)){
         case 0:{
           aux->restrictAsOutput(South);
           break;
         }
         case 1:{
           aux->restrictAsOutput(East);
           break;
         }
         default:break;
       }
     break;
   }
   case 6: {
     aux= new ElbowDownLeft();
     if ((unsigned int)r->getRandomNumber(1,100)<=fixed_coef)
       aux->setFixed(true);
     if ((unsigned int)r->getRandomNumber(1,100)<=res_coef)
       switch (r->getRandomNumber(0, 1)){
         case 0:{
           aux->restrictAsOutput(South);
           break;
         }
         case 1:{
           aux->restrictAsOutput(West);
           break;
         }
         default:break;
       }
   }
     break;
 }
 delete r;
 return aux;
}

