import ddf.minim.*;

Minim minim;
SE SE;
AudioPlayer BGMPlayer;
AudioPlayer BGSPlayer;

Input input;
Player player;
Level level;
Room room;
Fade fade;

String gameState;
boolean pause;
int currentRoom;

ArrayList <Enemy> enemies = new ArrayList <Enemy> ();
ArrayList <Candle> candles = new ArrayList <Candle> ();
ArrayList <DamageArea> damageAreas = new ArrayList <DamageArea> ();
ArrayList <Effect> effects = new ArrayList <Effect> ();
//ArrayList <OrderedObjects> enemies = new ArrayList <Object> ();

int animation;

PImage redIdle[] = new PImage [4];
PImage redWalk[] = new PImage [4];
PImage redThrow[] = new PImage [2];

PImage candleOn[] = new PImage [4];
PImage candlePower[] = new PImage [4];
PImage candleOff[] = new PImage [1];

PImage ghostIdle[] = new PImage [1];
PImage ghostDamage[] = new PImage [1];
PImage ghostChasing[] = new PImage [1];

PImage bigGhostIdle[] = new PImage [1];
PImage bigGhostDamage[] = new PImage [1];
PImage bigGhostChasing[] = new PImage [1];

PImage kingGhostIdle[] = new PImage [3];
PImage kingGhostDamage[] = new PImage [1];
PImage kingGhostChasing[] = new PImage [3];


PImage skullIdle[] = new PImage [4];
PImage skullDamage[] = new PImage [1];

PImage poof[] = new PImage [4];

PImage titleImg;
PImage introImg;
PImage gameOverImg;
PImage bgImg;
PImage tutorialImg;
PImage lastRoomImg;
PImage victoryImg;
PImage pauseImg;

PImage doorLocked;
PImage doorUnlocked;

PImage hudHeader;
PImage hudHeart;
PImage hudCandle;
PImage cursorImg;

PFont font;

void setup (){
  size (800, 600);
  //surface.setResizable(true);
  input = new Input();
  fade = new Fade();
  
  noCursor();
  //fullScreen();
  
  for (int i = 0; i<redIdle.length; i++) redIdle[i]= loadImage("Assets/Red/idle/red_iddle_"+i+".png");
  for (int i = 0; i<redWalk.length; i++) redWalk[i]= loadImage("Assets/Red/walk/red_walking_"+i+".png");
  for (int i = 0; i<redThrow.length; i++) redThrow[i]= loadImage("Assets/Red/throw/red_throw_"+i+".png");
  
  for (int i = 0; i<candleOn.length; i++) candleOn[i]= loadImage("Assets/Candle/vela_"+i+".png");
  for (int i = 0; i<candlePower.length; i++) candlePower[i]= loadImage("Assets/Candle/vela_power_"+i+".png");
  for (int i = 0; i<candleOff.length; i++) candleOff[i]= loadImage("Assets/Candle/vela_apagada_"+i+".png");
  
  for (int i = 0; i<ghostIdle.length; i++) ghostIdle[i]= loadImage("Assets/Ghost/ghost_idle_"+i+".png");
  for (int i = 0; i<ghostDamage.length; i++) ghostDamage[i]= loadImage("Assets/Ghost/ghost_hurt_"+i+".png");
  for (int i = 0; i<ghostChasing.length; i++) ghostChasing[i]= loadImage("Assets/Ghost/ghost_aggro_"+i+".png");
  
  for (int i = 0; i<bigGhostIdle.length; i++) bigGhostIdle[i]= loadImage("Assets/BigGhost/big_ghost_idle_"+i+".png");
  for (int i = 0; i<bigGhostDamage.length; i++) bigGhostDamage[i]= loadImage("Assets/BigGhost/big_ghost_hurt_"+i+".png");
  for (int i = 0; i<bigGhostChasing.length; i++) bigGhostChasing[i]= loadImage("Assets/BigGhost/big_ghost_chasing_"+i+".png");
  
  for (int i = 0; i<kingGhostIdle.length; i++) kingGhostIdle[i]= loadImage("Assets/King/king_idle_"+i+".png");
  for (int i = 0; i<kingGhostDamage.length; i++) kingGhostDamage[i]= loadImage("Assets/King/king_hurt_"+i+".png");
  for (int i = 0; i<kingGhostChasing.length; i++) kingGhostChasing[i]= loadImage("Assets/King/king_agro_"+i+".png");
  
  for (int i = 0; i<skullIdle.length; i++) skullIdle[i]= loadImage("Assets/FlamingSkull/skull_idle_"+i+".png");
  for (int i = 0; i<skullDamage.length; i++) skullDamage[i]= loadImage("Assets/FlamingSkull/skull_damage_"+i+".png");
  
  for (int i = 0; i<poof.length; i++) poof[i]= loadImage("Assets/Poof/poof_"+i+".png");
  
  titleImg = loadImage("Assets/title_screen.png");
  introImg = loadImage("Assets/intro_screen.png");
  gameOverImg = loadImage("Assets/game_over_screen.png");
  bgImg = loadImage("Assets/BG.png");
  tutorialImg = loadImage("Assets/tutorial_screen.png");
  lastRoomImg = loadImage("Assets/last_floor.png");
  victoryImg = loadImage("Assets/victory_screen.png");
  pauseImg = loadImage("Assets/paused_screen.png");
  
  hudHeader = loadImage("Assets/Red/header.png");
  hudHeart = loadImage("Assets/hud_heart.png");
  hudCandle = loadImage("Assets/hud_candle.png");
  cursorImg = loadImage("Assets/cursor.png");
  
  doorLocked = loadImage("Assets/door_locked.png");
  doorUnlocked = loadImage("Assets/door_unlocked.png");
  
  font = loadFont("SFAtarianSystem-28.vlw");
  textFont(font);
   
  SE = new SE();
  minim = new Minim (this);
  SE.initAllSounds();
  BGMPlayer = minim.loadFile("Assets/sound/mus_menu.wav");
  BGSPlayer = minim.loadFile("Assets/sound/mus_muted.wav");
  //BGMPlayer.loop();
  
  gameState = "title";
  setBGM("mus_menu");
  
}

void draw(){
  input.check();
  switch(gameState){
    case "title":
      titleRender();
      titleUpdate();
      break;
    case "intro":
      introRender();
      introUpdate();
      break;
    case "game":
        gameRender();
        if (!pause && !fade.fading){
          gameUpdate();
        }
        else if (pause){
          pauseRender();
          pauseUpdate();
        }
      break;
    case "gameOver":
      gameOverRender();
      gameOverUpdate();
      break;
    case "endGame":
      endGameRender();
      endGameUpdate();
      break;
  }
  if (!gameState.equals("game")) fade.render();
  fade.update();
        
  input.end();
}

void titleRender(){
  image(titleImg,0,0);
}
void titleUpdate(){
  if (!fade.fading){
    if(input.mouseLeft.justPressed){
      fade.start(120, color(255), "intro");
      SE.trigger(SE.menuConfirm);
    }
    else if (input.Q.justPressed){
      exit();
    }
  }
}

void introRender(){
  image(introImg,0,0);
}
void introUpdate(){
  if (!fade.fading && input.mouseLeft.justPressed){
    fade.start(120, color(255), "startGame");
  }
}

void gameRender(){
  
  //pushMatrix();
  //translate(-player.x, -player.y);
  level.render();
  //popMatrix();
  
  for (DamageArea d : damageAreas) d.render();  
  player.render();
  for (Candle c : candles) c.render();
  for (Effect f : effects) f.render();
  for (Enemy e : enemies) e.render();
  fade.render();
  renderHUD();
}

void gameUpdate(){
  animation++;
  if (animation > 200000) animation = 0;
  fade.update();  
  
  level.update();
  player.update();
  
  ArrayList <Candle> candlesToActivate = new ArrayList <Candle> ();
  ArrayList <Candle> candlesToRemove = new ArrayList <Candle> ();
  
  Point [] points = new Point [3];
  
  for (Candle c : candles) {
    c.update();
    if (candlesToActivate.size() < 3 && !c.flying && !c.activated) {
      candlesToActivate.add(c);
    }
    if (candlesToActivate.size() == 3) {
      int i = 0;
      for (Candle ca : candlesToActivate) {
        ca.activate();
        points[i] = new Point (ca.x, ca.y);
        i++;
      }
      SE.trigger(SE.ignite);
      DamageArea d = new DamageArea(points);
      damageAreas.add(d);
      candlesToActivate.clear();
    }
    if (!c.lit && player.hitBox.overlap(c.hitBox)){
      SE.trigger(SE.collect);
      candlesToRemove.add(c);
    }
  }
  for (Candle c : candlesToRemove) {
    candles.remove(c);
  }
  
  ArrayList <DamageArea> areasToRemove = new ArrayList <DamageArea> ();
  for (DamageArea d : damageAreas) {
    d.update();
    if(d.timer<0) areasToRemove.add(d);
  }
  for (DamageArea d : areasToRemove) {
    damageAreas.remove(d);
  }
  
  ArrayList <Enemy> enemiesToRemove = new ArrayList <Enemy> ();
  for (Enemy e : enemies) {
    if (e.flinch <= 0) {
      if (player.flinch <= 0 && player.hitBox.overlap(e.hitBox)) {
        player.takeDamage(e.power);
      }
      for (DamageArea d : damageAreas) {
        if (isInsideTriangle(e.x, e.y, d.points[0].x, d.points[0].y, d.points[1].x, d.points[1].y, d.points[2].x, d.points[2].y)){
          e.takeDamage(d.power);
        }
      }
    }
    e.update();
    if (!e.active) {
      enemiesToRemove.add(e);
      effects.add(new Effect(e.x, e.y));
    }
  }
  for (Enemy e : enemiesToRemove) {
    enemies.remove(e);
  }
  
  ArrayList <Effect> effectsToRemove = new ArrayList <Effect> ();
  for (Effect f : effects) {
    f.update();
    if (!f.active){
      effectsToRemove.add(f);
    }
  }
  for (Effect f : effectsToRemove) {
    effects.remove(f);
  }
  
  
  if (input.start.justPressed || input.esc.justPressed){
    pause = true;
  }
}

void pauseRender(){
  image(pauseImg,0,0);
}
void pauseUpdate(){
  if (input.start.justPressed || input.esc.justPressed){
    pause = false;
  }
  if (input.Q.justPressed){
    gameState = "title";
    pause = false;
  }
}


void gameOverRender(){
  image(gameOverImg,0,0);
}
void gameOverUpdate(){
  if (!fade.fading && input.mouseLeft.justPressed){
    fade.start(60, color(255), "startGame");
  }
  if (!fade.fading && input.Q.justPressed){
    gameState = "title";
  }
}

void endGameRender(){
  image(victoryImg,0,0);
}
void endGameUpdate(){
  if (!fade.fading && input.mouseLeft.justPressed){
    gameState = "title";
  }
}


void startGame(){
  gameState = "game";
  setBGM("mus_gameplay");
  level = new Level();
  player = new Player();

  currentRoom = 0;
  level.loadRoom(currentRoom);
}

void clearRoom(){
  candles.clear();
  enemies.clear();
  damageAreas.clear();  
}

void imageX(PImage I, float X, float Y, boolean b) {
  if (!b){
    pushMatrix();
    translate(X + I.width, 0);
    scale(-1, 1);
    image (I, 0, Y);
    popMatrix();
  }
  else{
    image (I, X, Y);
  }
}

void imageY(PImage I, float X, float Y) {
  pushMatrix();
  translate(0, Y + I.height);
  scale(1, -1);
  image (I, X, 0);
  popMatrix();
}