#include <GL/gl.h>
#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>
#include <sys/timeb.h>
#include "control.h"
#include "cube.h"
#include "twist.h"
#include "matrix.h"

float rot[16];
float roti[16];

bool reference = false;
int mousex, mousey;

void invert_rot() {
  for (int i = 0, ii = 0; i < 4; i++, ii += 4) {
    for (int j = 0, jj = 0; j < 4; j++, jj += 4) {
      roti[ii + j] = rot[i + jj];
    }
  }
}

void mouseinout(int state) {
  reference = false;
}

void mousebutton(int button, int state, int x, int y) {
  if (state != GLUT_DOWN) return;
  bool ccw = button == GLUT_LEFT_BUTTON;

  queue_twist(cube.front_face(), ccw);
}

void mousemove(int x, int y) {
  int dx = x - mousex;
  int dy = mousey - y;
  mousex = x;
  mousey = y;

  if (!reference) {
    reference = true;
    return;
  }

  if (dx == 0 && dy == 0) return;

  float dh = sqrt(dx * dx + dy * dy);

  invert_rot();
  float axis[4] = {-dy, dx, 0, 1};
  matrixmult(roti, axis);

  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glLoadMatrixf(rot);
  glRotatef(dh, axis[0], axis[1], axis[2]);
  glGetFloatv(GL_MODELVIEW_MATRIX, rot);
  glPopMatrix();

  glutPostRedisplay();
}

void keypress(unsigned char k, int x, int y) {
  if (k == 27 || k == 'q') exit(0);
  if (k == 'x' || k == 'X') cube.scramble(), glutPostRedisplay();
  if (k == 'r' || k == 'R') cube.reset(), glutPostRedisplay();
  // cube faces: right, top, front, left, bottom, back
  if (k == 'g') queue_twist(cube.front_face(0), 0);
  if (k == 'd') queue_twist(cube.front_face(1), 0);
  if (k == 'a') queue_twist(cube.front_face(2), 0);
  if (k == 's') queue_twist(cube.front_face(3), 0);
  if (k == 'f') queue_twist(cube.front_face(4), 0);
  if (k == 'e') queue_twist(cube.front_face(5), 0);
}
