#include "gametools.h"

#include "scene_if.h"
#include "gamewidget.h"
#include "gamestock.h"
#include "gamebonus.h"
#include "gameprofile.h"
#include "gamesound.h"

#include "hammertool.h"
#include "bighammertool.h"
#include "smallhammertool.h"
#include "bombtool.h"
#include "thundertool.h"
#include "clocktool.h"
#include "randomkilltool.h"
#include "mixertool.h"
#include "unblocktool.h"
#include "twintool.h"

#include "consttools.h"

ToolSet * toolset = 0;

////////////////////////////////////////////////////////////////////////////////

int GameTool::stage;

GameTool::GameTool(int x, int y, int score) :
    myPos(x,y),
    myScore(score),
    myToolset(0),
    myProgress(0),
    myActive(false)
{
}

GameTool::GameTool(int x, int y, int score, const QString &resource) :
    myPos(x,y),
    myScore(score),
    myToolset(0),
    myProgress(0),
    myActive(false)
{
  myPixmap = QPixmap(GameWidget::getResourcePath() + "/tools/" + resource + ".png")
             .scaled(48,48, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}

GameTool::~GameTool()
{
}

void GameTool::setCurrent()
{
  stage = TOOL_STAGES;
}

void GameTool::advanceAndPaint(QPainter &p, int currentScore)
{
  if (!myActive)
  {
    if (currentScore >= myScore)
    {
      setActive(true);
      animateActivation();
      myToolset->nextToolActivated();
    }
    return;
  }

  p.setOpacity(currentScore >= myScore ? 1 : 0.3);

  p.setPen(QPen(Qt::white));

  p.drawText(QRect(myPos.x(), myPos.y()-12, 48, 20), Qt::AlignHCenter | Qt::AlignTop, QString::number(myScore));

  if (myToolset->current() == this)
  {
    p.setOpacity((1.0/TOOL_STAGES) * stage);
    if (!--stage) stage = TOOL_STAGES;
  }

  p.drawPixmap(myPos, myPixmap);
}

void GameTool::animateActivation()
{
  scene->createPixmapPopup(myPos.x(), myPos.y(), -1, -1, myPixmap, 20);
  scene->createPixmapPopup(myPos.x(), myPos.y(), 1, 1, myPixmap, 20);
  scene->createPixmapPopup(myPos.x(), myPos.y(), -1, 1, myPixmap, 20);
  scene->createPixmapPopup(myPos.x(), myPos.y(), 1, -1, myPixmap, 20);
}

QString GameTool::hint() const
{
  return QString("%1: %2").arg(bonusInfo->name, bonusInfo->comment);
}

////////////////////////////////////////////////////////////////////////////////

ToolSet::ToolSet() : toolScore(0), currentTool(0)
{
  int x1 = 906, x2 = 965;
  int y = 290, dy = 65;

  smallHammerTool = new SmallHammerTool(x1,y, 750);

  clockTool = new ClockTool(x2,y, 1000);

  y += dy;

  mixerTool = new MixerTool(x1,y, 1250);

  unblockTool = new UnblockTool(x2,y, 1500);

  y += dy;

  hammerTool = new HammerTool(x1,y, 1750);

  bigHammerTool = new BigHammerTool(x2,y, 2000);

  y += dy;

  bombTool = new BombTool(x1,y, 2250);

  thunderTool = new ThunderTool(x2,y, 2500);

  y += dy;

  randomKillTool = new RandomKillTool(x1,y, 2750);

  twinTool = new TwinTool(x2,y, 3000);


  // permanent tools
  y += 100;
  magBonus = new MagBonus(x1,y, 4000);
  timerBonus = new TimerBonus(x2,y, 5000);
  y += dy;
  scoreBonus = new ScoreBonus(x1,y, 6000);
  clockBonus = new ClockBonus(x2,y, 7000);


  // order in which the tools are given
  tools.append(smallHammerTool);
  tools.append(clockTool);
  tools.append(mixerTool);
  tools.append(unblockTool);
  tools.append(hammerTool);
  tools.append(bigHammerTool);
  tools.append(bombTool);
  tools.append(thunderTool);
  tools.append(randomKillTool);
  tools.append(twinTool);

  tools.append(magBonus);
  tools.append(timerBonus);
  tools.append(scoreBonus);
  tools.append(clockBonus);


  for (int i = 0; i < tools.count(); i++)
  {
    GameTool *tool = tools.at(i);
    tool->setBase(this);
  }

  // active by default
  smallHammerTool->setActive();
  unblockTool->setActive();
}

ToolSet::~ToolSet()
{
  qDeleteAll(tools);
}

int ToolSet::bonusClock() const { return clockBonus->value(); }
int ToolSet::bonusScore() const { return scoreBonus->value(); }
int ToolSet::bonusTimer() const { return timerBonus->value(); }
int ToolSet::bonusMag() const { return magBonus->value(); }

void ToolSet::readProfile(PlayerInfo *pl)
{
  next_tool = pl->next_tool;
  toolScore = pl->localScore;

  diff = pl->diff;
  puzzle = pl->mode;

  currentTool = 0;

  diff = pl->diff;
  puzzle = pl->mode;

  for (int i = 0; i < tools.count(); i++)
  {
    bool act = i < 2 ? true : (!puzzle && (i < next_tool || !next_tool));

    tools.at(i)->setActive(act);
  }

  scoreBonus->setValue(pl->score_bonus);
  clockBonus->setValue(pl->time_bonus);
  timerBonus->setValue(pl->speed_bonus);
  magBonus->setValue(pl->speed_mag_bonus);
}

void ToolSet::writeProfile(PlayerInfo *pl)
{
  pl->next_tool = next_tool;
  pl->localScore = toolScore;

  pl->score_bonus = scoreBonus->value();
  pl->time_bonus = clockBonus->value();
  pl->speed_bonus = timerBonus->value();
  pl->speed_mag_bonus = magBonus->value();
}

void ToolSet::addScore(int score)
{
  toolScore += score;
}

void ToolSet::nextToolActivated()
{
  if (++next_tool >= tools.count())
    next_tool = 0;

  sndEngine->playSound(GameSound::sndTool);
}

int ToolSet::activeToolIndex(int score)
{
  int idx = 2;
  while (tools.at(idx)->score() <= score)
    idx++;
  if (idx == tools.count())
    idx = 0;
  return idx;
}

void ToolSet::updateTools(QPainter &p)
{
  p.setOpacity(1);
  p.setPen(QPen(Qt::lightGray));
  p.setFont(gameStock->Font20);

  int y = 270;

  p.drawText(910, y, QString("%1").arg(toolScore, 7, 10, QChar(' ')));

  p.setFont(gameStock->Font8);

  for (int i = 0; i < tools.count(); i++)
  {
    GameTool *tool = tools.at(i);
    tool->advanceAndPaint(p, toolScore);
  }
}

bool ToolSet::checkMouseActions(const QPoint &pos)
{
  for (int i = 0; i < tools.count(); i++)
  {
    GameTool *tool = tools.at(i);
    if (QRect(tool->pos(), QSize(48,48)).contains(pos))
    {
      if (!tool->isActive())
        return false;

      if (tool->score() <= toolScore)
      {
        currentTool = tool;
        currentTool->setCurrent();
        QApplication::setOverrideCursor(currentTool->pixmap());

        if (tool->type() != GameTool::ManualTool)
        {
          if (tool->checkToolClick())
          {
              toolScore -= tool->score();
              if (tool->inProgress())
                return true;
              else
                break;
          }
        }
        else  // manual tool
        {
        }

        myOverRow = myOverCol = -1;
        return true;
      }

      break;
    }
  }

  currentTool = 0;
  scene->setDefaultGameCursor();
  return false;
}

void ToolSet::progressCurrent()
{
  if (!(currentTool->checkToolClick()))
  {
    currentTool = 0;
    scene->setDefaultGameCursor();
  }
}

bool ToolSet::checkItemClick(int row, int col)
{
  if (!currentTool->checkItemClick(row, col))
    return false;

  toolScore -= currentTool->score();
  currentTool = 0;
  scene->setDefaultGameCursor();
  return true;
}

GameTool::ToolAction ToolSet::checkItemState(int row, int col)
{
  if (!currentTool || myOverCol == -1 || myOverRow == -1)
    return GameTool::ToolOutOfRange;

  return currentTool->checkItemState(row, col);
}

void ToolSet::checkMouseMoved(int row, int col)
{
  if (col >= 0 && col < scene->numCols() && row >= 0 && row < scene->numRows())
  {
    myOverRow = row;
    myOverCol = col;
  }
  else
    myOverRow = myOverCol = -1;
}

bool ToolSet::checkMouseHover(const QPoint &pos)
{
  for (int i = 0; i < tools.count(); i++)
  {
    GameTool *tool = tools.at(i);
    if (QRect(tool->pos(), QSize(48,48)).contains(pos) && tool->isActive())
    {
      scene->showHint(tool->hint());
      return true;
    }
  }

  return false;
}
