#include "./BFX/BFX.dnh"

InstallFont(GetCurrentScriptDirectory() ~ "./Fonts/Russell Square Regular.ttf");

/* 
let die = SoundSFX(GSD~"./../lib/se/morri.wav");

	BFX_Explosion(bx, by, 100, 60*1);
	wait(60*1/2);
	
	StartSlow(TARGET_ALL, 15);
		PlaySFX(die);
		BFX_Explosion(bx, by, 300, 60*1);
		wait(60*2);
	StopSlow(TARGET_ALL); 
	
	DeleteShotAll(TYPE_ALL, TYPE_FADE);
	wait(60*1); */
	
function angtoP(obj){
	return atan2(py - ObjMove_GetY(obj), px - ObjMove_GetX(obj));
}
	
function angtoB(obj){
	return atan2(by - ObjMove_GetY(obj), bx - ObjMove_GetX(obj));
}	
	
function stgw(){
	return GetStgFrameWidth();
}

function stgh(){
	return GetStgFrameHeight();
}

function px(){
    return GetPlayerX();
}

function py(){
    return GetPlayerY();
}

function bx(){
    return ObjMove_GetX(objBoss);
}

function by(){
    return ObjMove_GetY(objBoss);
}

function gx(){
    return GetStgFrameWidth() / 2;
}

function gy(){
    return GetStgFrameHeight() / 2;
}

function wait(n){loop(n){yield;}}
function lerp(start,end,t){return (1-t)*start+t*end;}
function blerp(x0,y0,x1,y1,t){return [lerp(x0,x1,t),lerp(y0,y1,t)];}
function NormalizeAngle(angle){ angle %= 360; if(angle<0){angle += 360;} return angle; }
function GetAngularDistance(angle1, angle2){ let distance = NormalizeAngle(angle2 - angle1); if(distance>180){ distance-=360; } return distance; }

task DisplayBGM(let r, let g, let b, let name){
	let obj = ObjText_Create();
	ObjText_SetFontSize(obj, 12);
	ObjText_SetFontBold(obj, false);
	ObjText_SetFontColorTop(obj, 255, 255, 255);
	ObjText_SetFontColorBottom(obj, r, g, b);
	ObjText_SetFontBorderType(obj, BORDER_FULL);
	ObjText_SetFontBorderColor(obj,0, 0, 0);
	ObjText_SetFontBorderWidth(obj, 1);
	ObjText_SetText(obj, "BGM:" ~ name);
	ObjRender_SetX(obj, 10);
	ObjRender_SetY(obj, GetStgFrameHeight());
	
	let y = 0;
	
	loop(60){
		ObjRender_SetY(obj, GetStgFrameHeight()-y);
	    y+=0.5;
		yield;
	}
	
	loop(60){yield;}
	
	loop(60){
		ObjRender_SetY(obj, GetStgFrameHeight()+y);
		yield;
		y-=0.5;
	}
	Obj_Delete(obj);
}

task DrawName(name, type){
	let objText = ObjText_Create();
	let alpha = 255;
	ObjText_SetText(objText, name);
	ObjText_SetFontType(objText, "Russell Square Regular");
	ObjText_SetFontSize(objText, 15);
	if(type == "MAMI"){
		ObjText_SetFontColorBottom(objText, 153, 102, 0);
		ObjText_SetFontColorTop(objText, 102, 51, 0);
	}
	if(type == "FIRE"){
		ObjText_SetFontColorTop(objText, 204, 51, 51);
		ObjText_SetFontColorBottom(objText, 166, 89, 89);
	}
	if(type == "YELLOW"){
		ObjText_SetFontColorBottom(objText, 255, 255, 102);
		ObjText_SetFontColorTop(objText, 179, 179, 0);
	}
	if(type == "DREAM"){
		ObjText_SetFontColorTop(objText, 255, 153, 255);
		ObjText_SetFontColorBottom(objText, 102, 0, 102);
	}
	ObjText_SetFontBorderType(objText, BORDER_SHADOW);
	ObjText_SetFontBorderColor(objText, 39, 24, 69);
	ObjText_SetFontBorderWidth(objText, 2);
	ObjText_SetHorizontalAlignment(objText, ALIGNMENT_LEFT);
	ObjRender_SetPosition(objText, 0, 10, 0);
	Obj_SetRenderPriority(objText,0.7);
	
	while(!Obj_IsDeleted(objBoss)){
		if(GetPlayerY > 80 && alpha < 255){
			alpha+=10;
		}
		if(GetPlayerY <= 80 && alpha > 100){
			alpha-=10;
		}
		ObjRender_SetAlpha(objText,alpha);
		yield;
	}
	
	Obj_Delete(objText);
}

task DrawAlert(name){
	let objText = ObjText_Create();
	let alpha = 255;
	ObjText_SetText(objText, name);
	ObjText_SetFontType(objText, "Russell Square Regular");
	ObjText_SetFontSize(objText, 14);
	ObjText_SetFontColorTop(objText, 204, 51, 51);
	ObjText_SetFontColorBottom(objText, 166, 89, 89);
	ObjText_SetFontBorderType(objText, BORDER_SHADOW);
	ObjText_SetFontBorderColor(objText, 39, 24, 69);
	ObjText_SetFontBorderWidth(objText, 3);
	ObjText_SetHorizontalAlignment(objText, ALIGNMENT_LEFT);
	ObjRender_SetPosition(objText, gx - 165, gy - 60, 0);
	Obj_SetRenderPriority(objText,0.7);
	
	while(!Obj_IsDeleted(objBoss)){
		if(GetPlayerY > 80 && alpha < 255){
			alpha+=10;
		}
		if(GetPlayerY <= 80 && alpha > 100){
			alpha-=10;
		}
		ObjRender_SetAlpha(objText,alpha);
		yield;
	}
	
	Obj_Delete(objText);
}


//Functions to do stuff with object dictionaries with less typing
function getval(obj,k){return Obj_GetValue(obj,k);}
function getvald(obj,k,d){return Obj_GetValueD(obj,k,d);}
function isval(obj,k){return Obj_IsValueExists(obj,k);}
function setval(obj,k,v){Obj_SetValue(obj,k,v);}
function setvalsf(obj,k,v){if(!Obj_IsDeleted(obj)){setval(obj,k,v);}}
function remval(obj,k){Obj_DeleteValue(obj,k);}

function setvals(obj,keys,vals){
	while(length(keys)>length(vals)){vals=vals~[NULL];}
	ascent(i in 0..length(keys)){
		if(vals[i]!=NO_CHANGE || !isval(obj,keys[i])){
			setval(obj,keys[i],vals[i]);
		}
	}
}

//Fuck it have some more laziness functions

function getx(obj){return ObjMove_GetX(obj);}
function gety(obj){return ObjMove_GetY(obj);}
function geta(obj){return ObjMove_GetAngle(obj);}
function getsp(obj){return ObjMove_GetSpeed(obj);}

function getrx(obj){return ObjRender_GetX(obj);}
function getry(obj){return ObjRender_GetY(obj);}
function getra(obj){return ObjRender_GetAngleZ(obj);}

function setx(obj,x){ObjMove_SetX(obj,x);}
function sety(obj,y){ObjMove_SetY(obj,y);}
function seta(obj,a){ObjMove_SetAngle(obj,a);}
function setsp(obj,s){ObjMove_SetSpeed(obj,s);}
function setpos(obj,x,y){ObjMove_SetPosition(obj,x,y);}
function setrpos(obj,x,y,z){ObjRender_SetPosition(obj,x,y,z);}

//check whether an object is safe to dereference
function isnull(obj){
	//can't check if it hasn't been set, initialize to NULL if there's a chance it'll come up
	if(!obj){return true;} //if it's null
	if(Obj_IsDeleted(obj)){return true;} //if it's been deleted
	return false;
}

function PolygonShot(x, y, range, speed, angle, way, way2, way_angle, graphic, delay){
    let bpos_x = [];
    let bpos_y = [];
    ascent(i in 0..way){
        let tmp_angle = 360 / way * i;
        bpos_x = bpos_x ~ [cos(tmp_angle)];
        bpos_y = bpos_y ~ [sin(tmp_angle)];
    }

    ascent(i in 0..way){
        let from_x = x + bpos_x[i % way];
        let from_y = y + bpos_y[i % way];
        let to_x = x + bpos_x[(i + way_angle) % way];
        let to_y = y + bpos_y[(i + way_angle) % way];

        ascent(j in 0..way2){
            let tmp = (j + 1) / way2;

            let vx = GetLinePosition(from_x, to_x, tmp);
            let vy = GetLinePosition(from_y, to_y, tmp);
            let dx = vx - x;
            let dy = vy - y;
            let va = atan2(dy, dx) + angle;
            let vs = (dx * dx + dy * dy) ^ 0.5;

            CreateShotA1(x + range*cos(va), y + range*sin(va), vs * speed, va, graphic, delay);
        }
    }
    
    function GetLinePosition(from_pos, to_pos, pos_t){
        return (from_pos + (to_pos - from_pos) * pos_t);
    }
}

function PolygonLaser(x, y, speed, angle, way, way2, way_angle, leng, thic, graphic, delay){
    let bpos_x = [];
    let bpos_y = [];
    ascent(i in 0..way){
        let tmp_angle = 360 / way * i;
        bpos_x = bpos_x ~ [cos(tmp_angle)];
        bpos_y = bpos_y ~ [sin(tmp_angle)];
    }

    ascent(i in 0..way){
        let from_x = x + bpos_x[i % way];
        let from_y = y + bpos_y[i % way];
        let to_x = x + bpos_x[(i + way_angle) % way];
        let to_y = y + bpos_y[(i + way_angle) % way];

        ascent(j in 0..way2){
            let tmp = (j + 1) / way2;

            let vx = GetLinePosition(from_x, to_x, tmp);
            let vy = GetLinePosition(from_y, to_y, tmp);
            let dx = vx - x;
            let dy = vy - y;
            let va = atan2(dy, dx) + angle;
            let vs = (dx * dx + dy * dy) ^ 0.5;

            //CreateShotA1(x, y, vs * speed, va, graphic, delay);
			CreateLooseLaserA1(x, y, vs*speed, va, leng, thic, graphic, delay);
        }
    }
    
    function GetLinePosition(from_pos, to_pos, pos_t){
        return (from_pos + (to_pos - from_pos) * pos_t);
    }
}

function CreateImageA1(pri, image){//thanks gt
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjRender_SetBlendType(obj, BLEND_ALPHA);
	Obj_SetRenderPriorityI(obj, pri);
	ObjPrim_SetTexture(obj, image);
	let test = [GetTextureWidth(image), GetTextureHeight(image)];
	ObjSprite2D_SetSourceRect(obj, 0, 0, test[0]-1, test[1]-1);
	ObjSprite2D_SetDestRect(obj, -(test[0]/2+0.5), -(test[1]/2), (test[0]/2), (test[1]/2));
	return obj;
}

function sec(i){ return 1/cos(i);}
function csc(i){ return 1/sin(i);}
function cot(i){ return 1/tan(i);}

function rand_int(low,high){
	return round(rand(low-0.49999,high+0.49999));
}