//  Testbed for making a match3 board
//  Created: 28/10/2017 09:05:33
//  John Ryland (jryland@xiaofrog.com)
//  InvertedLogic, (C) Copyright 2017
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <pthread.h>
#include "board.h"
#include "windowing.h"
#include "game.h"
#include "curves.h"
#include "common.h"

int letterIndex(char ch)
{
  const int startIdx = 9 + 4;
  if (ch >= '0' && ch <= '9')
    return ch - '0' + startIdx;
  if (ch == '@') return startIdx + 10;
  if (ch == '$') return startIdx + 11;
  if (ch == '%') return startIdx + 12;
  if (ch >= 'a' && ch <= 'z')
    return ch - 'a' + startIdx + 13;
  if (ch >= 'A' && ch <= 'Z')
    return ch - 'A' + startIdx + 13 + 13 + 13;
  return 0;
}

/*
  Add debug menu
     - add display of curves by graphing them
*/
class MyWindow : public CanvasWindow
{
public:
  MyWindow()
  {
    loadSpriteSheet(spriteSheet, "data/sprites-32x32.txt");
    getCurveFunctionNames(m_curves);
    curveIdx = -1;
    nextCurve();
  }
  ~MyWindow()
  {
  }
  void drawText(int x, int y, const char* text)
  {
    while (*text) {
      if (!isspace(*text))
        drawSprite(buffer, x, y, spriteSheet.sprites[letterIndex(*text)], 255);
      x += 14;
      text++;
    }
  }
  void onDraw(int x1, int y1, int x2, int y2)
  {
    CanvasWindow::onDraw(x1, y1, x2, y2);

/*
    for (int i = 0; i < 1000; i++) {
      vec2f pnt = KochanekBartelsSpline(testCurve, float(i) / 1000.0); // a_tension = 0.0f, a_bias = 0.0f, a_continuity = 0.0f
      buffer.pixels[ int(buffer.h - 1 - pnt.y) * buffer.w + int(pnt.x) ] = 0xFFFFFFFF;
    }
*/

    // The easing curves
    if (!curve.empty()) {
      // clear and draw label for the graph
      for (int i = 0; i < buffer.w - 100; i++)
        for (int j = 10; j < 80; j++)
          buffer.pixels[ int(j) * buffer.w + int(50 + i) ] = 0xFFFFFFFF;
      drawText(60, (buffer.h/2)-30, curve.c_str());

      // draw the axes
      for (int i = 0; i < 350; i++) {
        buffer.pixels[ int(150+0*350) * buffer.w + int(50 + i) ] = 0xFFFFFFFF;
        buffer.pixels[ int(150+    i) * buffer.w + int(50 + 0) ] = 0xFFFFFFFF;
      }

      // prepare line segment list of the curve
      testCurve.clear();
      for (int i = 0; i < 100; i++) {
        float y = evaluateCurve(curve.c_str(), float(i) / 100.0);
        testCurve.push_back((vec2f){ float(i) / 100.0, y });
      }

      // plot the curve
      for (int i = 0; i < 100000; i++) {
        vec2f pnt = lineSpline(testCurve, float(i) / 100000.0);
        buffer.pixels[ int(150+pnt.y*350) * buffer.w + int(50 + pnt.x*350) ] = 0xFF3FFF3F;
      }
    }
  }
  void onMouseEvent(int x, int y, int buttons)
  {
    static int oldButtons = 0;
    if (!oldButtons && buttons) {
      //printf("adding point\n");
      //testCurve.push_back((vec2f){ x, y });
      nextCurve();
    }
    oldButtons = buttons;
  }
  void nextCurve()
  {
    curveIdx++;
    if (curveIdx >= m_curves.size())
      curveIdx = 0;
    curve = m_curves[curveIdx];
    memset(buffer.pixels.data(), 0, buffer.w*buffer.h*4);
  }
private:
  SpriteSheet spriteSheet;
  std::vector<vec2f> testCurve;
  std::string curve;
  std::vector<std::string> m_curves;
  int curveIdx;
};

class MyApp : public Application
{
public:
  void onStart()
  {
    window.create(480, 650);
  }
private:
  MyWindow window;
};

int main(int argc, char ** argv)
{
  MyApp app;
  return app.run();
}

