#include <QPainter>
#include <QKeyEvent>
#include "GameVis.h"


GameVis::GameVis()
{
  m_gameSim = new GameSim();
  m_ownSim = true;
  reset();
}


GameVis::GameVis(GameSim* a_gameSim)
{
  m_gameSim = a_gameSim;
  m_ownSim = false;
  reset();
}


GameVis::~GameVis()
{
  if (m_ownSim)
     delete m_gameSim;
}


void GameVis::reset()
{
  m_running = true;
  m_isoX = -620;
  m_isoY = 250;
  m_isoDX = 0;
  m_isoDY = 0;
  m_logoTicks = 20;
  startTimer(100);
  m_f[0] = 5; m_f[1] = 5; m_f[2] = -3; m_f[3] = 3;
}


void GameVis::timerEvent(QTimerEvent*)
{
  if (m_running)
  {
    if (m_logoTicks)
      m_logoTicks--;
    m_gameSim->update(1);
    if (m_gameSim->isGameOver())
    {
      m_running = false;
    }
  }
  update();
}


void GameVis::keyPressEvent(QKeyEvent* a_ke)
{
  if (a_ke->key() == Qt::Key_Down)
    m_gameSim->movePlayer(Backward);
  if (a_ke->key() == Qt::Key_Up)
    m_gameSim->movePlayer(Forward);
  if (a_ke->key() == Qt::Key_Left)
    m_gameSim->movePlayer(Left);
  if (a_ke->key() == Qt::Key_Right)
    m_gameSim->movePlayer(Right);

  if (a_ke->key() == Qt::Key_W)
    m_isoY += 20;
  if (a_ke->key() == Qt::Key_S)
    m_isoY -= 20;
  if (a_ke->key() == Qt::Key_A)
    m_isoX -= 20;
  if (a_ke->key() == Qt::Key_D)
    m_isoX += 20;

  if (a_ke->key() == Qt::Key_U) m_f[0]++;
  if (a_ke->key() == Qt::Key_I) m_f[1]++;
  if (a_ke->key() == Qt::Key_O) m_f[2]++;
  if (a_ke->key() == Qt::Key_P) m_f[3]++;
  if (a_ke->key() == Qt::Key_H) m_f[0]--;
  if (a_ke->key() == Qt::Key_J) m_f[1]--;
  if (a_ke->key() == Qt::Key_K) m_f[2]--;
  if (a_ke->key() == Qt::Key_L) m_f[3]--;

  printf("m_f = %i,%i,%i,%i  x,y = %i,%i\n", m_f[0], m_f[1], m_f[2], m_f[3], m_isoX, m_isoY);
}


void GameVis::mousePressEvent(QMouseEvent*)
{
  m_gameSim->movePlayer(Forward);
  if (!m_running)
  {
    m_gameSim->reset();
    m_running = true;
    m_logoTicks = 20;
  }
}


// 50x19
const char* logo =
    "--***********-**********-**********-************--"
    "--*+++++++++*-*++++++++*-*++++++++*-*++++++++++*--"
    "--*+++++++++*-*++++++++*-*++++++++*-*++++++++++*--"
    "--*+++++++++*-*++++++++*-*++++++++*-*++++++++++*--"
    "--****+++****-*+++******-*+++******-****+++*****--"
    "-----*+++*----*+++*------*+++*---------*+++*------"
    "-----*+++*----*+++*------*+++*---------*+++*------"
    "-----*+++*----*+++****---*+++******----*+++*------"
    "-----*+++*----*++++++*---*++++++++*----*+++*------"
    "-----*+++*----*++++++*---*++++++++*----*+++*------"
    "-----*+++*----*++++++*---*++++++++*----*+++*------"
    "-----*+++*----*+++****---******+++*----*+++*------"
    "-----*+++*----*+++*-----------*+++*----*+++*------"
    "-----*+++*----*+++*-----------*+++*----*+++*------"
    "-----*+++*----*+++******-******+++*----*+++*------"
    "-----*+++*----*++++++++*-*++++++++*----*+++*------"
    "-----*+++*----*++++++++*-*++++++++*----*+++*------"
    "-----*+++*----*++++++++*-*++++++++*----*+++*------"
    "-----*****----**********-**********----*****------";


void GameVis::paintEvent(QPaintEvent*)
{
  QPainter p(this);

  const int orientation = 3;
  const int o = orientation;
  const float scale = 0.3;
  const float m[5][4] = { 
    { 1, 0, 0, 1 },
    { scale * 5, scale * 5, scale * -3, scale * 3 },
    { scale * m_f[0], scale * m_f[1], scale * m_f[2], scale * m_f[3] },
    { scale * 9, scale * 3, scale * 2, scale * -6 },
    { scale * 5, scale * 5, scale * -3, scale * 3 }
  };

  std::vector<GameObjectList*> objLists = m_gameSim->objectLists();
  GameObject& player = objLists.back()->front();

  // if show logo
  GameObjectList logoList;
  if (m_logoTicks)
  {
    for (int j = 18; j >= 0; j--)
      for (int i = 0; i < 50; i++)
      {
        char ch = logo[j*50+i];
        if (ch != '-')
        {
          GameObject item;
          item.m_type = Bonus;
          item.m_color = (ch == '+') ? 0xffffff : 0;
          item.m_x = 180 + i*5;
          item.m_y = 50;
          item.m_w = 5;
          item.m_h = 20;
          item.m_z = 20 + (19-j)*7;
          item.m_d = 7;
          logoList.push_back(item);
        }
      }
    objLists.push_back(&logoList);
  }

  for (GameObjectList* objList : objLists)
  {
    for (const GameObject& obj : *objList)
    {
      p.setPen(QColor(QRgb(0)));

      uint32_t color = obj.m_color;

      switch (obj.m_type)
      {
        // Terrain
        case Ground:        color = 0x47bd37; break; 
        case Road:          color = 0x6a6963; break;
        case Rail:          color = 0x464441; break;
        case Water:         color = 0x3a31f5; break;
        case WaterLane:     color = 0x3a31f5; break;

        // Obstacles
        case Tree:          color = 0x508c23; break;
        case Shrub:         color = 0x508c23; break;
        case Building:      color = 0xd38b37; break;
        case Rocks:         color = 0x5c4932; break;

        // Vehicles
        case Bike:          color = 0xdf1f24; break;
        case Car:           color = 0xf52542; break;
        case Van:           color = 0x3a4b88; break;
        case Truck:         color = 0xdfd41f; break;

        // Trains
        case Train1:        color = 0x8bbb38; break;
        case Train2:        color = 0xa2d051; break;
        case Train3:        color = 0x6ca50a; break;
        case Train4:        color = 0x0a53a5; break;

        // Vessels
        case Log:           color = 0x6b5331; break;
        case Boat:          color = 0xd5d5d5; break;
        case Crocodile:     color = 0x597e3e; break;
        case LilyPad:       color = 0x71df1f; break;
        case SteppingStone: color = 0x71df1f; break;

        case Player:        color = 0xffffff; break;

        // Pickups
        case Coin:          color = 0xffffff; break;
        case Food:          color = 0xffffff; break;
        case Life:          color = 0xffffff; break;
        //case Bonus:         color = 0xffffff; break;

        default:
            break;
      }

      p.setBrush(QColor(QRgb(color)));

      float xs[4] = { obj.m_x, obj.m_x + obj.m_w, obj.m_x + obj.m_w, obj.m_x };
      float ys[8] = { obj.m_y, obj.m_y, obj.m_y + obj.m_h, obj.m_y + obj.m_h };

      int pnts1[8] = {
        m_isoX + int(xs[0] * m[o][0] + ys[0] * m[o][1]), m_isoY + int(xs[0] * m[o][2] + ys[0] * m[o][3]) - obj.m_z,
        m_isoX + int(xs[1] * m[o][0] + ys[1] * m[o][1]), m_isoY + int(xs[1] * m[o][2] + ys[1] * m[o][3]) - obj.m_z,
        m_isoX + int(xs[2] * m[o][0] + ys[2] * m[o][1]), m_isoY + int(xs[2] * m[o][2] + ys[2] * m[o][3]) - obj.m_z,
        m_isoX + int(xs[3] * m[o][0] + ys[3] * m[o][1]), m_isoY + int(xs[3] * m[o][2] + ys[3] * m[o][3]) - obj.m_z
      };
      int pnts2[8] = {
        m_isoX + int(xs[0] * m[o][0] + ys[0] * m[o][1]), m_isoY + int(xs[0] * m[o][2] + ys[0] * m[o][3]) - (obj.m_z + obj.m_d),
        m_isoX + int(xs[1] * m[o][0] + ys[1] * m[o][1]), m_isoY + int(xs[1] * m[o][2] + ys[1] * m[o][3]) - (obj.m_z + obj.m_d),
        m_isoX + int(xs[2] * m[o][0] + ys[2] * m[o][1]), m_isoY + int(xs[2] * m[o][2] + ys[2] * m[o][3]) - (obj.m_z + obj.m_d),
        m_isoX + int(xs[3] * m[o][0] + ys[3] * m[o][1]), m_isoY + int(xs[3] * m[o][2] + ys[3] * m[o][3]) - (obj.m_z + obj.m_d)
      };
      int pnts3[8] = {
        pnts1[0], pnts1[1], pnts1[2], pnts1[3],
        pnts2[2], pnts2[3], pnts2[0], pnts2[1]
      };
      int pnts4[8] = {
        pnts1[2], pnts1[3], pnts1[4], pnts1[5],
        pnts2[4], pnts2[5], pnts2[2], pnts2[3]
      };
      p.drawPolygon(QPolygon(4, pnts1));
      p.drawPolygon(QPolygon(4, pnts2));
      p.drawPolygon(QPolygon(4, pnts3));
      p.drawPolygon(QPolygon(4, pnts4));
    }
  }

  float playerX = player.m_x;
  float playerY = player.m_y;
  int playerScreenX = int(playerX * m[o][0] + playerY * m[o][1]);
  int playerScreenY = int(playerX * m[o][2] + playerY * m[o][3]);
  m_isoX = (width()/2) - playerScreenX;
  m_isoY = (height() - 150) - playerScreenY;

  if (!m_running)
  {
    p.setPen(QColor(QRgb(0x2fd6d8)));
    QFont f = p.font();
    f.setPointSize(24);
    p.setFont(f);
    if (m_gameSim->hasWon())
    {
      p.drawText(270, 210, "You Won!");
    }
    else
    {
      p.drawText(270, 210, "You Lost!");
    }
    p.drawText(270, 250, "Game Over");
    p.drawText(240, 290, "Click to Restart");
  }
}



