
#include <string>
#include <cstring>
#include <memory>
#include <cstdlib>

#include "graphics/mode7.hpp"

#include "flight.hpp"
#include "assets.hpp"

using namespace blit;

const uint16_t screen_width = 160;
const uint16_t screen_height = 120;

// extra space allocated to take mipmaps
// mipmaps are stored as Pen since they're the blended result of scaling the paletted image data
uint8_t __sprites[(128 * 128) + (64 * 128 * sizeof(Pen))];

// storage for the water spritesheet
uint8_t __water[64 * 64];

/* create surfaces */
Surface *sprites;
Surface *water;

Map map(Rect(0, 0, 128, 128));

struct object {
  Vec2 pos;
  uint8_t type;

  object(Vec2 pos, uint8_t type) : pos(pos), type(type) {}
};

struct DrawObject {
  object o;
  float dist;
  Vec2 vs;
  
  DrawObject(object obj, float dist, Vec2 vs): o(obj), dist(dist), vs(vs) {}

  bool operator< (const DrawObject &other) const {
        return other.dist < dist;
    }
};

std::vector<object> objects;

static Vec2 vel(0, 0);
static float angle = -15.0f * (pi / 180.0f);
Vec2 pos(512, 512);

float map_size = 128;
float fov = 95.0f * (pi / 180.0f);
float far = 500.0f;
float near = 10.0f;
float is_starting = false;

float deg2rad(float a) {
  return a * (pi / 180.0f);
}

float rad2deg(float r) {
  return r * (180.0f / pi);
}

void init() {
  map.add_layer("ground", layer);
  map.layers["ground"].transforms = layer_transforms;

  // Load our map sprites into the __sprites space we've reserved
  sprites = Surface::load(packed_data, __sprites, sizeof(__sprites));
  sprites->generate_mipmaps(3);

  water = Surface::load(water_packed_data, __water, sizeof(__water));

  // extract information about objects from the map data
  Point p;
  for (p.y = 0; p.y < 128; p.y++) {
    for (p.x = 0; p.x < 128; p.x++) {
      int16_t tid = map.layers["ground"].tile_at(p);
      if (tid == 27) {
        objects.emplace_back(
          Vec2(p.x * 8 + 4, p.y * 8 + 4),
          1
        );
      }
      if (tid == 28) {
        objects.emplace_back(
          Vec2(p.x * 8 + 4, p.y * 8 + 4),
          2
        );
      }
      if (tid == 29) {
        objects.emplace_back(
          Vec2(p.x * 8 + 4, p.y * 8 + 4),
          3
        );
      }
      if (tid == 30) {
        objects.emplace_back(
          Vec2(p.x * 8 + 4, p.y * 8 + 4),
          4
        );
      }
    }
  }
}

/* get normalised value off 255 for the dist of object between the above values. 
  So if min is 300 and max is 800, if the distance is 400, we would want to get a scale of the alpha
*/
float calculateFadeAlpha (const int maxDist, const int minDist, float dist) {
  int range = maxDist - minDist;
  int n = dist - minDist;
  float percentage = n / float(range);
  return 1.0f - (255.0f * percentage);
}

Rect vp(0, 50, 160, 120 - 50);

// returns vector of objects that are viewable
std::vector<DrawObject> drawObjects (std::vector<object> objects) {
  std::vector<DrawObject> vect;

  for (auto o : objects) {
    Vec2 vo = (o.pos - pos);
    vo.normalize();
    Vec2 forward(0, -1);
    forward *= Mat3::rotation(angle);

    // TODO: provide a "is_point_in_frustrum" check
    if(forward.dot(vo) > 0) { // check if object is in front of us
      Vec2 vs = world_to_screen(o.pos, fov, angle, pos, near, far, vp);
      float dist = (o.pos - pos).length();
      
      vect.push_back(DrawObject(o,dist,vs));
    }
  }

  return vect;
}

void render(uint32_t time_ms) {
  static int tick_count = 0; tick_count++;

  screen.alpha = 255;
  screen.mask = nullptr;
  screen.pen = Pen(99, 155, 255);
  screen.rectangle(Rect(0, 0, 160, 50));

  screen.pen = Pen(91, 110, 225);
  screen.rectangle(Rect(0, 50, 160, 120 - 50));
  uint32_t ms_start = now();

  screen.alpha = 55;

  screen.blit(water, Rect(0, 0, 64, 64), Point(0, 50));

  mode7(&screen, sprites, &map.layers["ground"], fov, angle, pos, near, far, vp);

  std::vector<DrawObject> drawables = drawObjects(objects);
  std::sort(drawables.begin(), drawables.end()); // sort them so they draw in order

  const int maxViewDistance = 600; // draw distance
  const int maxClearDistance = 300; // before sprites stop being fully opaque. start to fade out.

  for (DrawObject o : drawables) {
   
    if (o.dist < float(maxViewDistance)) { // check if the object is in a reasonable distance

      if (o.dist > maxClearDistance) {
        screen.alpha = calculateFadeAlpha(maxViewDistance, maxClearDistance, o.dist);
      } else {
        screen.alpha = 255.0f;
      }

      Rect sr(120, 112, 8, 16);

      screen.blit(sprites, sr, o.vs - Point(4, 15));
    }
  }

  uint32_t ms_end = now();

  // Orientation debug info
  screen.alpha = 255;
  screen.pen = Pen(255, 255, 255);
  screen.text("N: " + std::to_string(int(near)) + " - F:" + std::to_string(int(far)), minimal_font, Rect(0, 0, 100, 10));
  screen.text("X: " + std::to_string(int(pos.x)) + " - Y:" + std::to_string(int(pos.y)), minimal_font, Rect(0, 10, 100, 10));
  screen.text("A: " + std::to_string(int(rad2deg(angle))), minimal_font, Rect(0, 20, 100, 10));

  // draw the mini map
  screen.alpha = 200;
  screen.pen = Pen(0, 0, 0, 100);
  screen.rectangle(Rect(160 - 64, 120 - 64, 64, 64));
  Vec2 mmp;
  for (mmp.y = 0; mmp.y < 64; mmp.y++) {
    for (mmp.x = 0; mmp.x < 64; mmp.x++) {
      Point tp = mmp * 2.0f;
      
      int16_t tile_id = map.layers["ground"].tile_at(tp) - 1;

      if (tile_id != -1) {
        Point sp(
          (tile_id & 0b1111),
          (tile_id / 16)
        ); // sprite sheet coordinates

        Pen *spr = (Pen *)sprites->mipmaps[2]->data;
        Pen *mmv = &spr[sp.x + sp.y * 16];
        screen.pen = *mmv;
        screen.pixel(mmp + Vec2(160 - 64, 120 - 64));
      }
    }
  }
  
  Vec2 mmpos = (pos / 16.0f) + Vec2(160 - 64, 120 - 64);
  screen.pen = Pen(255, 255, 255);
  screen.pixel(mmpos);

  Vec2 mtpos = (Vec2(400, 400) / 16.0f) + Vec2(160 - 64, 120 - 64);
  screen.pen = Pen(0, 255, 255);
  screen.pixel(mtpos);

  Vec2 forward(0, -10);
  forward *= Mat3::rotation(angle);
  screen.pen = Pen(255, 255, 255, 100);
  screen.line(mmpos, mmpos + forward);

  // draw FPS meter
  screen.alpha = 255;
  screen.pen = Pen(255, 255, 255, 100);
  screen.rectangle(Rect(1, 120 - 10, 12, 9));
  screen.pen = Pen(255, 255, 255, 200);
  std::string fms = std::to_string(ms_end - ms_start);
  screen.text(fms, minimal_font, Rect(3, 120 - 9, 10, 16));

  int block_size = 4;
  for (uint32_t i = 0; i < (ms_end - ms_start); i++) {
    screen.pen = Pen(i * 5, 255 - (i * 5), 0);
    screen.rectangle(Rect(i * (block_size + 1) + 1 + 13, screen.bounds.h - block_size - 1, block_size, block_size));
  }
}

bool compare (float v1, float v2) {
  return fabsf(v1 - v2) < 0.001f;
}

bool is_off_ground () {
  return !compare(500.0f, far);
}

float lerping(float a, float b, float f) {
    return a + f * (b - a);
}

void update(uint32_t time) {
  
  static float angle_delta = 0.0f;
  float target_speed;
  float lerp_value = 0.002f;

  if (pressed(Button::DPAD_LEFT))  { angle_delta += 0.05f; }
  if (pressed(Button::DPAD_RIGHT)) { angle_delta -= 0.05f; }

  angle_delta -= joystick.x / 80.0f ;

  if (pressed(Button::Y)) { 
    // boost button
      target_speed = is_off_ground() ? 2.0f : 0.5f;
  } else {
      target_speed = is_off_ground() ? 0.8f : 0.0f;
  }

  if (pressed(Button::X))  { 
    // break button
    target_speed = is_off_ground() ? 0.5f : 0.0f;

    if (!is_off_ground()) {
      lerp_value *= 5.0f;
    }
  }

  angle += deg2rad(angle_delta);   
  Mat3 r = Mat3::rotation(angle);    
  pos = pos - (vel * r);

  if (pressed(Button::A) || (joystick.y > 0.0f)) {
    far = far + (far * 0.01f);
  }
  if (pressed(Button::B) || (joystick.y < 0.0f)) {
    far = far - (far * 0.01f);
    far = std::max(far,500.0f);
  }

  angle_delta *= 0.95f;

  vel.y = lerping(vel.y, target_speed, 0.002f);

}
