#include "particle.h"
#include "camera.h"
#include "globals.h"

const int MAX_PARTICLE_SIZE=150;
std::vector<Particle *> particles;

std::vector<Particle *> particle_models;


void LoadParticles() {
  Particle *p;
  p = new Particle(0, 0, "Snow01", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Snow02", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Snow03", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Snow04", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Snow05", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Snow06", 10);
  particle_models.push_back(p);

  p = new Particle(0, 0, "Hit01", 10);
  particle_models.push_back(p);

  p = new Particle(0, 0, "Sparkle01", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Sparkle02", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Sparkle03", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Sparkle04", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Sparkle05", 10);
  particle_models.push_back(p);

  p = new Particle(0, 0, "Gift01", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Gift02", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Gift03", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Gift04", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Gift05", 10);
  particle_models.push_back(p);
  p = new Particle(0, 0, "Gift06", 10);
  particle_models.push_back(p);


  p = new Particle(0, 0, "Torch01", 10);
  particle_models.push_back(p);

}

void AddParticle(int i, float x, float y, float sp, Vec2D dir, float lf) {
  Particle *p;
  p = new Particle(x, y, particle_models[i], lf, dir, sp);
  p->SetType(i);
  particles.push_back(p);
}


void CheckParticlesSize() {
  int sz;
  sz = particles.size();

  if (sz > MAX_PARTICLE_SIZE) {
    sz -= MAX_PARTICLE_SIZE;
    int i;
    for (i=0; i!=sz; i+=1) {
      particles[i]->Kill();
    }
  }
}


void DeleteParticleList() {
  std::vector<Particle *>::iterator it;
  for (it=particles.begin(); it != particles.end(); it += 1) {
    delete (*it);
  }
  particles.clear();
}


void CleanParticlesList() {
  std::vector<Particle *> oldlist;
  std::vector<Particle *>::iterator it;
  oldlist.clear();
  for (it=particles.begin(); it != particles.end(); it += 1) {
    if (!(*it)->Erase()) oldlist.push_back((*it));
    else {
      delete (*it);
    }
  }
  particles.clear();
  for (it=oldlist.begin(); it != oldlist.end(); it += 1) {
    particles.push_back((*it));
  }
  oldlist.clear();
}

void UpdateParticles() {
  static int NextCleanup=10;
  NextCleanup -= 1;
  if (NextCleanup <= 0) {
    NextCleanup = 10;
    CheckParticlesSize();
    CleanParticlesList();
  }
  std::vector<Particle *>::iterator it;
  for (it = particles.begin(); it!=particles.end(); it+=1) {
    (*it)->Update();
  }
}

void DrawParticles() {
  std::vector<Particle *>::iterator it;
  for (it = particles.begin(); it!=particles.end(); it+=1) {
    (*it)->Draw();
  }
}

Particle::Particle(float tx, float ty, std::string path, float lf) {
  x = tx;
  y = ty;
  sprite.Load("Particles/" + path);
  opacity=1.0;
  life = lf;
  Reset();
}


Particle::Particle(float tx, float ty, Particle *p, float lf, Vec2D dir, float sp) {
  x = tx;
  y = ty;
  sprite.Copy(p->GetSprite());
  opacity=1.0;
  life = lf;
  direction = dir;
  speed = sp;
  Reset();
}

Particle::~Particle() {
  sprite.Clear();
}

void Particle::Reset() {
  erasing=erased=false;
}

void Particle::UpdateGeneral() {
  if (life > 0) life -= DeltaTime;
  if ((type >= PARTICLE_SPARKLE_01) && (type <= PARTICLE_SPARKLE_05)) ;
  else speed -= (speed/10)*DeltaTime;
  if (speed < 0) speed = 0;
  x += direction.x*speed;
  y += direction.y*speed;
  if (life <= 0) erasing=true;
  if (erasing) {
    opacity -= 0.01;
    if (opacity <= 0) erased = true;
  }
}


void Particle::Draw() {
  CacheBitmap *bit;
  bit = sprite.GetActualBitmap();
  if (opacity < 0) opacity = 0;
  if (opacity > 1) opacity = 1;
  OPACITY_BLEND(opacity);
  DRAW_TRANSFORMED(bit->get_bit(), rx, ry, RSW(bit->Width()), RSH(bit->Height()), angle, 0);
  NORMAL_BLEND;
}
