#include <string.h>
#include <stdio.h>
#include <math.h>
#include "hardscene.h"

unsigned char code[BC_SEGMENTS * BC_SEGMENTS];
unsigned char music[BC_SEGMENTS * BC_SEGMENTS];
unsigned char grfx[BC_SEGMENTS * BC_SEGMENTS];

void openRAW(unsigned char *data, char *filename){
  FILE *rawfile;

  rawfile = fopen(filename, "rb");
  fread(data, sizeof(char), BC_SEGMENTS * BC_SEGMENTS, rawfile);
  fclose(rawfile);
}

void loadHardSceneData(){
   openRAW(code,  "data/travis.raw");
   openRAW(music, "data/shamen.raw");
   openRAW(grfx,  "data/grass.raw");
}

void hairycube(double time, unsigned char *surface, float *eye){
  int i, j;

  for(i = 0; i < BC_SEGMENTS; i++){
     for(j = 0; j < BC_SEGMENTS; j++){
        surface[i * BC_SEGMENTS + j] = 127.0 + sin((float)(i-time)*(float)(j-time) / 25.0) * 20.0;
     }
  }
  eye[0] = 6.0;
  eye[1] = 5.0;
  eye[2] = 6.0;
}

void codecube(double time, unsigned char *surface, float *eye){
   memcpy(surface, code, BC_SEGMENTS * BC_SEGMENTS);
   eye[0] = 3.0 * sin(time / 3.0);
   eye[1] = 0.0;
   eye[2] = 3.0 * cos(time / 2.0);
}

void musiccube(double time, unsigned char *surface, float *eye){
   memcpy(surface, music, BC_SEGMENTS * BC_SEGMENTS);
   eye[0] = 3.0 * sin(time / 3.0);
   eye[1] = 0.0;
   eye[2] = 3.0 * cos(time / 2.0);
}

void grfxcube(double time, unsigned char *surface, float *eye){
   memcpy(surface, grfx, BC_SEGMENTS * BC_SEGMENTS);
   eye[0] = 3.0 * sin(time / 3.0);
   eye[1] = 0.0;
   eye[2] = 3.0 * cos(time / 2.0);
}

void circlecube(double time, unsigned char *surface, float *eye){
   int i,j;

   for(i = 0; i < BC_SEGMENTS; i++){
      for(j = 0; j < BC_SEGMENTS; j++){
          surface[i * BC_SEGMENTS + j] = 127.0 + sin((float)i*(float)j / 25.0) * 20.0 * sin(time);
      }
   }
   eye[0] = 9.0 * sin(time * -2.0);
   eye[1] = sin(time) * 2.0;
   eye[2] = 9.0 * cos(time * -2.0);
}

void wavycube(double time, unsigned char *surface, float *eye){
   int i,j;

   for(i = 0; i < BC_SEGMENTS; i++){
      for(j = 0; j < BC_SEGMENTS; j++){
         surface[i * BC_SEGMENTS + j] = (sin((float)i)*(fabs(sin(time*8.0)*4.0)) + 127.0)/5.0 * 
                                        (sin((float)j)*(fabs(sin(time*8.0)*4.0)) + 127.0)/5.0;
      }
   }

   eye[0] = 8.0 * sin(time * 2.0);
   eye[1] = 8.0 * cos(time * 2.0);
}

void spherecube(double time, unsigned char *surface, float *eye){
   int i,j;

   for(i = 0; i < BC_SEGMENTS; i++){
      for(j = 0; j < BC_SEGMENTS; j++){
         surface[i * BC_SEGMENTS + j] = 127.0 + ((float)(i-12) * (float)(i-12) + (float)(j-12) * (float)(j-12)) * sin(time*2.0) / 5.0;
      }
   }

   eye[0] = 0.0;
   eye[1] = 0.0;
   eye[2] = 6.5 + sin(time * 4.0) * 2.0;
}

/* Parameter changing for hard scene */
int hardSceneParameters(double time, unsigned char *surface, float *eye){
   int newtime;

   newtime = (time * 2.0 - 70.314) / 1.739;

   if(time < 72.051){
      hairycube(time, surface, eye);
   }
   else{
      switch(newtime % 6){
      case 0:
         spherecube(time, surface, eye);
         break;
      case 1:
         codecube(time, surface, eye);
         break;
      case 2:
         wavycube(time, surface, eye);
         break;
      case 3:
         musiccube(time, surface, eye);
         break;
      case 4:
         circlecube(time, surface, eye);
         break;
      case 5:
         grfxcube(time, surface, eye);
         break;
      }
   }

   return(newtime % 6);
}
