#include_function "lib\Ikareimu\Common\Math.dnh"
#include_function "lib\Ikareimu\Common\Effects.dnh"
#include_function "lib\Ikareimu\System\Polarity.dnh"
#include_function "lib\Ikareimu\System\Power.dnh"
#include_function "lib\Ikareimu\System\Collision.dnh"

/******************************************
* Variables                               *
******************************************/

let Power                = GetCommonDataDefault("power", 0);

let RedLasers            = [];
let BlueLasers           = [];

let OBJ_LASER_ID         = 0;
let OBJ_LASER_TYPE       = 1;
let OBJ_LASER_ORG_LENGTH = 2;

/******************************************
* Public Functions                        *
******************************************/

// Used in the same way as Obj_Create(OBJ_SHOT) and
// Obj_Create(OBJ_LASER)but adds the id into an array.
function ColorLaser_Create(color, type, x, y, speed, angle, length, width, graphic, delay){
  let obj = Obj_Create(OBJ_LASER);
  Obj_SetPosition(obj, x, y);
  Obj_SetSpeed(obj, speed);
  Obj_SetAngle(obj, angle);
  ObjLaser_SetLength(obj, length);
  ObjLaser_SetWidth(obj, width);
  ObjShot_SetGraphic(obj, graphic);
  ObjShot_SetDelay(obj, delay);
  if(color==RED){
    RedLasers = RedLasers ~ [[obj, type, length]];
  }
  else if(color==BLUE){
    BlueLasers = BlueLasers ~ [[obj, type, length]];
  }
  return obj;
}



// Laser type 1 cuts the laser without letting it grow back
// and deletes the laser if the player absorbs the source
// It moves independent of the enemy in the angle it's set at.
// The speed parameter makes this laser move at that speed towards
// the angle it's facing

// Laser type 2 returns the laser to its previous length when
// the player moves out of the way. Also pushes the
// player slightly in the direction of the laser's angle.
// It is installed on at a point. The speed parameter does not
// affect this laser type.
function ObjLaser_Red_GetType(obj){
  return RedLasers[ObjLaser_getIndex(obj, RedLasers)][OBJ_LASER_TYPE];
}
function ObjLaser_Blue_GetType(obj){
  return BlueLasers[ObjLaser_getIndex(obj, BlueLasers)][OBJ_LASER_TYPE];
}


// Manages the absorption and collision of lasers.
sub LaserManager_Run {
  ObjLaser_Red_manage;
  ObjLaser_Blue_manage;
}

/******************************************
* Private Functions                       *
******************************************/
// What are you looking here for? Are you crazy? The slightest
// breeze of wind in here and... OH NOW LOOK WHAT YOU DID!!
// ...I better clean this place up later.

function ObjLaser_getIndex(obj, array){
  let len = length(array);
  ascent (i in 0..len){
    if (array[i][OBJ_LASER_ID] == obj){
      return i;
    }
  }
  RaiseError( "Object ID not found!", "Bullet Absorption System Error");
}

sub ObjLaser_Red_manage {
  let len = length(RedLasers);
  descent (i in 0..len){
    let obj = RedLasers[i][OBJ_LASER_ID];
    let type = RedLasers[i][OBJ_LASER_TYPE];
    if (Obj_BeDeleted(obj)){
      RedLasers = erase(RedLasers, i);
    }
    else {
      if (type == 1){
        ObjLaser_SetSource(obj, false);
        ObjLaser_Red_1_manage(obj, i);
      }
      else {
        ObjLaser_SetSource(obj, true);
        ObjLaser_Red_2_manage(obj, i);
      }
    }
  }
}

function ObjLaser_Red_1_manage(obj, i){
  let x = Obj_GetX(obj);
  let y = Obj_GetY(obj);
  let angle = Obj_GetAngle(obj);
  let speed = Obj_GetSpeed(obj);
  Obj_SetPosition(obj, x+cos(angle)*speed, y+sin(angle)*speed);
  if (ObjCollision_GetState == ON){
    if (GetPolarity == RED){
      Obj_SetCollisionToPlayer(obj, false);
      if (GetDistanceFromPlayer(x, y) <17){
        Obj_Delete(obj);
        RedLasers = erase(RedLasers, i);
        AddPower(0.05);  
        AddScore(1);    
      }
      else {
        while (ObjCollision_Happened(obj)){
          ObjLaser_SetLength(obj, ObjLaser_GetLength(obj)-1);
          AddPower(0.05);
          AddScore(1);
        }
      }
    }
  }
  else {
    Obj_SetCollisionToPlayer(obj, true);
  }
}

function ObjLaser_Red_2_manage(obj, i){
  let x = Obj_GetX(obj);
  let y = Obj_GetY(obj);
  let EndX = ObjLaser_GetEndX(obj);
  let EndY = ObjLaser_GetEndY(obj);
  let angle = Obj_GetAngle(obj);
  let originalLength = RedLasers[i][OBJ_LASER_ORG_LENGTH];
  let newLength = ObjLaser_GetLength(obj)+34;
  if (newLength > originalLength){
    newLength = originalLength;
  }
  ObjLaser_SetLength(obj, newLength);

  if (ObjCollision_GetState == ON){
    if (GetPolarity == RED){
      Obj_SetCollisionToPlayer(obj, false);
      if (ObjCollision_Happened(obj)){
        SetPlayerX(GetPlayerX+cos(angle)*0.5);
        SetPlayerY(GetPlayerY+sin(angle)*0.5);
        while (ObjCollision_Happened(obj)){
          ObjLaser_SetLength(obj, ObjLaser_GetLength(obj)-1);
        }
        ObjLaser_SetLength(obj, ObjLaser_GetLength(obj)-24);
        AddPower(0.3);
        AddScore(5);
        AbsorbEffect_B_create(EndX-cos(angle)*8, EndY-sin(angle)*8, RED01);
      }
    }
  }
  else {
    Obj_SetCollisionToPlayer(obj, true);
  }
}

sub ObjLaser_Blue_manage {
  let len = length(BlueLasers);
  descent (i in 0..len){
    let obj = BlueLasers[i][OBJ_LASER_ID];
    let type = BlueLasers[i][OBJ_LASER_TYPE];
    if (Obj_BeDeleted(obj)){
      BlueLasers = erase(BlueLasers, i);
    }
    else {
      if (type == 1){
        ObjLaser_SetSource(obj, false);
        ObjLaser_Blue_1_manage(obj, i);
      }
      else if(type == 2){
        ObjLaser_SetSource(obj, true);
        ObjLaser_Blue_2_manage(obj, i);
      }
    }
  }
}

function ObjLaser_Blue_1_manage(obj, i){
  let x = Obj_GetX(obj);
  let y = Obj_GetY(obj);
  let angle = Obj_GetAngle(obj);
  let speed = Obj_GetSpeed(obj);
  Obj_SetPosition(obj, x+cos(angle)*speed, y+sin(angle)*speed);
  if (ObjCollision_GetState == ON){
    if (GetPolarity == BLUE){
      Obj_SetCollisionToPlayer(obj, false);
      if (GetDistanceFromPlayer(x, y) <17){
        Obj_Delete(obj);
        BlueLasers = erase(BlueLasers, i);
        AddPower(0.05);  
        AddScore(1);    
      }
      else {
        while (ObjCollision_Happened(obj)){
          ObjLaser_SetLength(obj, ObjLaser_GetLength(obj)-1);
          AddPower(0.05);
          AddScore(1);
        }
      }
    }
    else {
      Obj_SetCollisionToPlayer(obj, true);
    }
  }
  else {
    Obj_SetCollisionToPlayer(obj, true);
  }
}

function ObjLaser_Blue_2_manage(obj, i){
  let x = Obj_GetX(obj);
  let y = Obj_GetY(obj);
  let EndX = ObjLaser_GetEndX(obj);
  let EndY = ObjLaser_GetEndY(obj);
  let angle = Obj_GetAngle(obj);
  let originalLength = BlueLasers[i][OBJ_LASER_ORG_LENGTH];
  let newLength = ObjLaser_GetLength(obj) + 34;
  if (newLength > originalLength){
    newLength = originalLength;
  }
  ObjLaser_SetLength(obj, newLength);
  if (ObjCollision_GetState == ON){
    if (GetPolarity == BLUE){
      Obj_SetCollisionToPlayer(obj, false);
      if (ObjCollision_Happened(obj)){
        SetPlayerX(GetPlayerX+cos(angle)*0.5);
        SetPlayerY(GetPlayerY+sin(angle)*0.5);
        while (ObjCollision_Happened(obj)){
          ObjLaser_SetLength(obj, ObjLaser_GetLength(obj)-1);
        }
        ObjLaser_SetLength(obj, ObjLaser_GetLength(obj)-24);
        AddPower(0.3);
        AddScore(5);
        AbsorbEffect_B_create(EndX-cos(angle)*8, EndY-sin(angle)*8, BLUE01);
      }
    }
    else {
      Obj_SetCollisionToPlayer(obj, true);
    }
  }
  else {
    Obj_SetCollisionToPlayer(obj, true);
  }
}