#include_function ".\bosslib\SpeedManageHelpers.dnh"
#include_function ".\bosslib\CommonDataHelpers.dnh"
#include_function ".\bosslib\CommonFunctions.dnh"
#include_function ".\bosslib\ScoreHelpers.dnh"

let imgDelay = GetCurrentScriptDirectory ~ "bosslib\img\delay.png";

let StbShots = [];
//STBSHOT_ID = 0;
//STBSHOT_SPEED = 1;
//STBSHOT_DELAY = 2;
//STBSHOT_SCORE = 3;
//STBSHOT_SIZE = 4;
//STBSHOT_COLOR = 5;
//STBSHOT_TIME = 6;

// This is called by InitializeStbBoss and manages the slowdown, pausing, and deletion of bullets.
task RunStbShotsManager {
  let GameSpeed = GetGameSpeed;
  loop {
    let area = GetCameraDeleteArea;
    let GameSpeedChanged = GameSpeed != GetGameSpeed;
    descent(i in 0..length(StbShots)){
      let ShotInfo = StbShots[i];
      if(Obj_BeDeleted(ShotInfo[0])){
        StbShots = erase(StbShots, i);
      }
      else {
        if(area != [-1, -1, -1, -1]){
          let collision = Collision_Line_Circle(area[0], (area[1]+area[3])/2, area[2], (area[1]+area[3])/2, area[3]-area[1], Obj_GetX(ShotInfo[0]), Obj_GetY(ShotInfo[0]), ShotInfo[4]);
          if(collision){
            SetShotDeleteEffectPositions(GetShotDeleteEffectPositions ~ [[Obj_GetX(ShotInfo[0]), Obj_GetY(ShotInfo[0]), ShotInfo[5], ShotInfo[4]]]);
            AddToBaseScore(ShotInfo[3], ShotInfo[5]);
            AddToRiskCount(Obj_GetX(ShotInfo[0]), Obj_GetY(ShotInfo[0]), ShotInfo[4]);
            Obj_Delete(ShotInfo[0]);
            StbShots = erase(StbShots, i);
          }
        }
        else {
          if(ShotInfo[6] < ShotInfo[2]){
          }
          else if(floor(ShotInfo[6]) == ShotInfo[2]){
            Obj_SetAlpha(ShotInfo[0], 255);
            Obj_SetCollisionToPlayer(ShotInfo[0], true);
            if(GetGameSpeed < 0){
              Obj_SetSpeed(ShotInfo[0], 0);
            }
            else {
              Obj_SetSpeed(ShotInfo[0], ShotInfo[1]*(1/(GetGameSpeed+1)));
            }
          }
          else if(GameSpeedChanged){
            if(GetGameSpeed < 0){
              Obj_SetSpeed(ShotInfo[0], 0);
            }
            else {
              Obj_SetSpeed(ShotInfo[0], ShotInfo[1]*(1/(GetGameSpeed+1)));
            }
          }
            
          if(GetGameSpeed >= 0){
            ShotInfo[6] = ShotInfo[6] + (1/(GetGameSpeed+1));
          }
          StbShots[i] = ShotInfo;
        }
      }
    }
    if(GetCameraDeleteArea != [-1, -1, -1, -1]){
      CalculateAndDisplayScore(area[0], area[1], area[2], area[3]);
    }
    if(GameSpeed != GetGameSpeed){
      GameSpeed = GetGameSpeed;
    }
    yield;
  }
  
}

task CreateStbDelay(x, y, color, duration){
  let obj = ObjEffect_InitializeRect(imgDelay, 5);
  let indx = ColorToNumber(color)*32;
  ObjEffect_SetUVRect(obj, indx, 0, indx+32, 32);
  ObjEffect_SetXYRect(obj, -16, -16, 16, 16);
  ObjEffect_SetColor(obj, 4, 255, 255, 255, 255);
  Obj_SetPosition(obj, x, y);
  
  let counter = duration;
  while(counter > 0){
    ObjEffect_SetScale(obj, 2/duration*counter, 2/duration*counter);
    
    if(GetGameSpeed >= 0){
      counter -= 1/(GetGameSpeed+1);
    }
    
    if(GetCameraDeleteArea != [-1, -1, -1, -1]){
      let area = GetCameraDeleteArea;
      if(IsPointInRectangle(x, y, area[0], area[1], area[2], area[3])){
        break;
      }
    }
    yield;
  }
  Obj_Delete(obj);
  
  function ColorToNumber(c){
    alternative(c)
    case(RED){ return 1; }
    case(PURPLE){ return 2; }
    case(BLUE){ return 3; }
    case(CYAN){ return 4; }
    case(GREEN){ return 5; }
    case(YELLOW){ return 6; }
    case(ORANGE){ return 7; }
    others { return 0; }
  }
}

// Works like Obj_Create(OBJ_SHOT)
function ObjStbShot_Create {
  let obj = Obj_Create(OBJ_SHOT);
  StbShots = StbShots ~ [[obj, 0, 0, 0, 0, 0, 0, 0]];
  Obj_SetAlpha(obj, 0);
  Obj_SetCollisionToPlayer(obj, false);
  return obj;
}

// Works similarly to ObjStbShot_Create, but calls all the necessary functions and
// fills out the rest of the array so that later function calls that cost more processing
// power can be skipped if desired.
function ObjStbShot_Initialize(x, y, speed, angle, graphic, delay, score, size, color){
  let obj = Obj_Create(OBJ_SHOT);
  Obj_SetPosition(obj, x, y);
  Obj_SetAngle(obj, angle);
  Obj_SetAlpha(obj, 0);
  Obj_SetCollisionToPlayer(obj, false);
  ObjShot_SetGraphic(obj, graphic);
  StbShots = StbShots ~ [[obj, speed, delay, score, size, color, 0]];
  return obj;
}

// Works like Obj_Delete
function ObjStbShot_Delete(id){
  Obj_Delete(id);
}

// Works like Obj_BeDeleted
function ObjStbShot_BeDeleted(id){
  return Obj_BeDeleted(id);
}

// Works like Obj_SetX
function ObjStbShot_SetX(id, x){
  Obj_SetX(id, x);
}

// Works like Obj_SetY
function ObjStbShot_SetY(id, y){
  Obj_SetY(id, y);
}

// Works like Obj_SetPosition
function ObjStbShot_SetPosition(id, x, y){
  Obj_SetPosition(id, x, y);
}

// Works like Obj_SetSpeed on the surface, but actually changes some data that
// is needed to manage slowdown and pausing
function ObjStbShot_SetSpeed(id, speed){
  let indx = GetArrayIndexById(id);
  if(indx==NULL){ return ; }
  let temparray = StbShots[indx];
  temparray[1] = speed;
  StbShots[indx] = temparray;

  if(floor(temparray[6] >= temparray[2]) && GetGameSpeed >= 0){
    Obj_SetSpeed(id, speed*(1/(GetGameSpeed+1)));;
  }
}

// Works like Obj_SetAngle
function ObjStbShot_SetAngle(id, angle){
  Obj_SetAngle(id, angle);
}

// Works like Obj_SetAutoDelete
function ObjStbShot_SetAutoDelete(id, bool){
  Obj_SetAutoDelete(id, bool);
}

// Works like Obj_SetAlpha
function ObjStbShot_SetAlpha(id, alpha){
  Obj_SetAlpha(id, alpha);
}

// Works like Obj_SetCollisionToPlayer
function ObjStbShot_SetCollisionToPlayer(id, bool){
  Obj_SetCollisionToPlayer(id, bool);
}

// Works like Obj_SetCollisionToObject
function ObjStbShot_SetCollisionToObject(id, bool){
  Obj_SetCollisionToObject(id, bool);
}

// Works like Obj_IsIntersected
function ObjStbShot_IsIntersected(id){
  return Obj_IsIntersected(id);
}

// Works like Obj_GetX
function ObjStbShot_GetX(id){
  return Obj_GetX(id);
}

// Works like Obj_GetY
function ObjStbShot_GetY(id){
  return Obj_GetY(id);
}

// Works like Obj_GetSpeed except instead of looking at the shot's actual
// speed, it takes the data stored in the array so that the same value is
// returned even during slowdown and pausing
function ObjStbShot_GetSpeed(id){
  let indx = GetArrayIndexById(id);
  if(indx==NULL){ return 0; }
  else { return StbShots[indx][1]; }
}

// Works like Obj_GetAngle
function ObjStbShot_GetAngle(id){
  return Obj_GetAngle(id);
}

// Works like ObjShot_FadeDelete
function ObjStbShot_FadeDelete(id){
  ObjShot_FadeDelete(id);
}

// Works like ObjShot_SetDelay on the surface, but actually changes some data that
// is needed to manage slowdown and pausing
function ObjStbShot_SetDelay(id, delay){
  let indx = GetArrayIndexById(id);
  if(indx==NULL){ return ; }
  let temparray = StbShots[indx];
  temparray[2] = delay;
  StbShots[indx] = temparray;
}

// Works like ObjShot_SetBombResist
function ObjStbShot_SetBombResist(id, bool){
  ObjShot_SetBombResist(id, bool);
}

// Works like ObjShot_SetGraphic
function ObjStbShot_SetGraphic(id, graphic){
  ObjShot_SetGraphic(id, graphic);
}

// Works like ObjShot_ToItem
function ObjStbShot_ToItem(id, bool){
  ObjShot_ToItem(id, bool);
}

// Sets the base score of the shot to be added with other shots in a picture
// when one is taken
function ObjStbShot_SetScore(id, score){
  let indx = GetArrayIndexById(id);
  if(indx==NULL){ return ; }
  let temparray = StbShots[indx];
  temparray[3] = score;
  StbShots[indx] = temparray;
}

// Sets the size of the shot that determines its hitbox relative to the picture
// frame. Does not change the hitbox size relative to the player or the graphic size
function ObjStbShot_SetSize(id, size){
  let indx = GetArrayIndexById(id);
  if(indx==NULL){ return ; }
  let temparray = StbShots[indx];
  temparray[4] = size;
  StbShots[indx] = temparray;
}

// Sets the color that determines what kind of effect it will turn into if it
// is deleted by the camera. Also influences color dependent bonuses such as
// Red Shot!, Orange Shot!, Rainbow Shot!, etc.
function ObjStbShot_SetColor(id, color){
  let indx = GetArrayIndexById(id);
  if(indx==NULL){ return ; }
  let temparray = StbShots[indx];
  temparray[5] = color;
  StbShots[indx] = temparray;
}

// Private functions.

function GetArrayIndexById(id){
  descent(i in 0..length(StbShots)){
    if(StbShots[i][0]==id){ return i; }
  }
  return NULL;
}