//  BlockyFroggy
//  Copyright © 2017 John Ryland.
//  All rights reserved.
#include "EditorState.h"
#include "GameSim.h"
#include "Dialog.h"
#include "Graphics.h"


REGISTER_GAME_STATE(EditorState)


const GameUi::Rectangle paletteRect = {  15, 480, 300, 300 };
const GameUi::Rectangle editorRect  = { 335, 555, 300, 150 };


void EditorState::enter(GameGraphics& graphics)
{
  std::vector<GameSim::GameObjectList*> objectLists;
  graphics.resetVertexBuffers( objectLists );
  for (unsigned i = 0; i < sizeof(m_palIdxMru)/sizeof(m_palIdxMru[0]); i++)
    m_palIdxMru[i] = 0;
}


void EditorState::exit(GameGraphics& /*graphics*/)
{
}


using namespace GameUi;


void addPixmapData(DrawItems& items, Rectangle screenGeometry, PixelData pixmap, Rectangle pixmapRect)
{
  PixelData& m_pixmap = pixmap;
  Rectangle& m_pixmapSlice = pixmapRect;
  Rectangle& m_geometry = screenGeometry;
  if (!m_pixmapSlice.w || !m_pixmapSlice.h)
    return;
  int pixW = m_geometry.w / m_pixmapSlice.w;
  int pixH = m_geometry.h / m_pixmapSlice.h;
  for (int j = 0; j < m_pixmapSlice.h; j++)
    for (int i = 0; i < m_pixmapSlice.w; i++) {
      int x = m_geometry.x + pixW * i;
      int y = m_geometry.y + pixH * j;
      size_t idx = (m_pixmapSlice.y + j) * m_pixmap.m_stride + m_pixmapSlice.x + i;
      if (idx < size_t(m_pixmap.m_stride * m_pixmap.m_rows)) {
        if (m_pixmap.m_data[idx].color) {
          items.addQuad(Rectangle{x, y, pixW, pixH}, Rectangle{179,113,30,30}, m_pixmap.m_data[idx]);
        } else {
          items.addQuad(Rectangle{x, y, pixW+1, pixH+1}, Rectangle{179,113,30,30}, 0xaf666666);
          items.addQuad(Rectangle{x+pixW/2, y, pixW/2, pixH/2}, Rectangle{180,114,29,29}, 0xafdddddd);
          items.addQuad(Rectangle{x, y+pixH/2, pixW/2, pixH/2}, Rectangle{180,114,29,29}, 0xafdddddd);
        }
      }
    }
}


void EditorState::draw(GameGraphics& graphics)
{
  static int lastLayer = -11;
  int editLayerI = (m_pixD-1) - int((m_pixD-1) * m_editLayer + 0.0);
  if (editLayerI != lastLayer || !m_pixels.size())
    graphics.getEditObjectPixels(m_editLayer, m_pixels, m_pixW, m_pixH, m_pixD);
  else
    graphics.setEditObjectPixels(m_editLayer, m_pixels, m_pixW, m_pixH);
  lastLayer = editLayerI;
  if (!m_palette.size())
    graphics.getPalettePixels(m_palette);
  int pw = paletteRect.w/16;
  int ph = paletteRect.h/16;
  int px = m_palIdx%16;
  int py = m_palIdx/16;

  // Draw bottom ui layer
  GameUi::DrawItems itemsUnder;
  addPixmapData(itemsUnder, paletteRect, { (GameUi::Color*)m_palette.data(),   16,   16 }, { 0, 0,   16,   16 });
  addPixmapData(itemsUnder, editorRect,  { (GameUi::Color*)m_pixels.data(), size_t(m_pixW), size_t(m_pixH) }, { 0, 0, m_pixW, m_pixH });

  int pixW = (paletteRect.w / 8) - 1;
  int pixH = (paletteRect.h / 8) - 1;
  for (int i = 0; i < 8; i++)
    itemsUnder.addQuad(Rectangle{paletteRect.x + i*pixW, paletteRect.y + 8*pixH, pixW, pixH}, Rectangle{179,113,30,30}, m_palette[m_palIdxMru[i]]);

  itemsUnder.addQuad({paletteRect.x + px*pw, paletteRect.y + py*ph, pw, ph}, { 160, 141, 2, 2 }, 0xff123456, 0);  
  itemsUnder.addIcon(paletteRect.x, paletteRect.y, 23, 0xff123456);

//  itemsUnder.addContrastString( 50,  160, "Text under");
  graphics.drawAuxItems(itemsUnder);

  // Draw 3D parts
  graphics.prepareScreenContext();

  graphics.setEditLayer(m_editLayer);
  graphics.setEditRotation(m_editRotation);
//  graphics.setEditModel(editModel);


/*
  // Draw ui overlay over everything
  GameUi::DrawItems itemsOver;
  itemsOver.addContrastString( 70,  220, "Text over");
  graphics.drawAuxItems(itemsOver);
*/
}


bool EditorState::update(GameUi::UpdateState& state, float elapsed)
{
  //GameUi::Button button(50, 50, "Blah");
  //button.onUpdate(items, a_elapsed);
  m_editLayer = atof(state.m_variables["EDIT_LAYER"].c_str());
  m_editRotation = atof(state.m_variables["EDIT_ROTATION"].c_str());
  return true; // has to be exited via ui
}


bool EditorState::touchesChanged(int a_x, int a_y, TouchState ts)
{
/*
  if (ts == TouchDown) {
    m_touchMoving = false;
    m_touchX = a_x;
    m_touchY = a_y;
  } else if (ts == TouchMove) {
    m_touchMoving = true;
  } else {
    if (m_touchMoving)
    {
      float dx = m_touchX - a_x;
      if (dx > 5 || dx < -5) {
        if (dx > 5)
          editModel++;
        if (dx < -5)
          editModel--;
        pixels.clear();
      }
    }
  }
*/

  if (ts == TouchDown || ts == TouchMove) {
    if (paletteRect.isInside({a_x,a_y})) {
      int x = (a_x - paletteRect.x) / (paletteRect.w/16);
      int y = (a_y - paletteRect.y) / (paletteRect.h/16);
      if (x >=0 && x < 16 && y >= 0 && y < 16) {
        m_palIdx = y*16+x;
        if (m_palIdx != m_palIdxMru[0])
          for (int i = (sizeof(m_palIdxMru)/sizeof(m_palIdxMru[0])) -1; i >= 1; i--)
            m_palIdxMru[i] = m_palIdxMru[i-1];
        m_palIdxMru[0] = m_palIdx;
      }
    }
    else if (m_pixW && m_pixH && editorRect.isInside({a_x,a_y})) {
      int x = (a_x - editorRect.x) / (editorRect.w/m_pixW);
      int y = (a_y - editorRect.y) / (editorRect.h/m_pixH);
      if (x >=0 && x < m_pixW && y >= 0 && y < m_pixH)
        m_pixIdx = y*m_pixW+x;

      if ( m_palIdx == 0 || m_palIdx == 1 || m_palIdx == 16 || m_palIdx == 17 ) // eraser
        m_pixels[m_pixIdx] = 0;
      else
        m_pixels[m_pixIdx] = m_palette[m_palIdx]; // painting with color
    }
  }
  return false; 
}


/*

void clipRendering(int x, int y, int w, int h)
{
  GLint vp[4];
  glGetIntegerv(GL_VIEWPORT, vp);
  GLdouble planes[4][4] = {
     { 1.0,  0.0, 0.0, -2.0 * x / float(vp[2]) + 1.0 },  //left
     { 0.0, -1.0, 0.0, -2.0 * y / float(vp[3]) + 1.0 }, //top
     {-1.0,  0.0, 0.0,  2.0 * (x+w) / float(vp[2]) - 1.0 }, //right
     { 0.0,  1.0, 0.0,  2.0 * (y+h) / float(vp[3]) - 1.0 }  //bottom
  };
  for (int i = 0; i < 4; i++) {
    glClipPlane(GL_CLIP_PLANE0+i, planes[i]);
    glEnable(GL_CLIP_PLANE0+i);
  }
}


void disableClip()
{
  for (int i = 0; i < 4; i++)
    glDisable(GL_CLIP_PLANE0+i);
}


void draw()
{
  //clipRendering(  6+2, 55+27, 304, 347 );

  GLint vp[4];
  glGetIntegerv(GL_VIEWPORT, vp);
  glViewport(6+2, vp[3]-(55+27+347), 304, 347);
  graphics.drawModelRotatingPreview();
  glViewport(vp[0], vp[1], vp[2], vp[3]);

  glClear(GL_DEPTH_BUFFER_BIT);
  clipRendering(324+2, 55+27, 304, 347 );
  graphics.drawModelEditLayer();
  disableClip();
}

*/

