
import{numberWithCommas}from"./numberUtils";

let SoopyV2Forge=Java.type("me.soopyboo32.soopyv2forge.SoopyV2Forge").INSTANCE;

let LASTEST_SOOPYFORGE_VER="1.1";
let canUseForgeRendering=net.minecraftforge.fml.common.Loader.isModLoaded("soopyv2forge");

let ArrayList=Java.type("java.util.ArrayList");

let Vec3=Java.type("net.minecraft.util.Vec3");
let Vector2f=Java.type("javax.vecmath.Vector2f");
let RenderPointsC=Java.type("me.soopyboo32.soopyv2forge.RenderTypes.Points");
let RenderWorldTextC=Java.type("me.soopyboo32.soopyv2forge.RenderTypes.WorldText");
let RenderBeaconC=Java.type("me.soopyboo32.soopyv2forge.RenderTypes.Beacon");
let HudPointsC=Java.type("me.soopyboo32.soopyv2forge.RenderTypes.HudPoints");
let HudTextC=Java.type("me.soopyboo32.soopyv2forge.RenderTypes.HudText");

let addFix=false;
if(!global.soopyv2RenderWorldThings){
global.soopyv2RenderWorldThings=new Set;
addFix=true;
}
if(!global.soopyv2RenderHudThings)global.soopyv2RenderHudThings=new Set;

register("gameUnload",()=>{
global.soopyv2RenderWorldThings.clear();
SoopyV2Forge.setRenderWorldList(new ArrayList([]));
global.soopyv2RenderHudThings.clear();
SoopyV2Forge.setRenderHudList(new ArrayList([]));
});

let currentlyRendering=true;
export function setRendering(rendering){
if(!rendering){
setRenderWorldList(new ArrayList([]));
setRenderHudList(new ArrayList([]));
}
currentlyRendering=rendering;
if(rendering){
setRenderWorldList(new ArrayList([global.soopyV2RenderfixLineThing,...global.soopyv2RenderWorldThings]));
setRenderHudList(new ArrayList([...global.soopyv2RenderHudThings]));
}
}

function setRenderWorldList(data){
if(currentlyRendering)SoopyV2Forge.setRenderWorldList(data);
}
function setRenderHudList(data){
if(currentlyRendering)SoopyV2Forge.setRenderHudList(data);
}

class RenderWorldAble{
startRender(isBatched){
if(!canUseForgeRendering)return;
if(global.soopyv2RenderWorldThings.has(this.javaObj))return this;
global.soopyv2RenderWorldThings.add(this.javaObj);
if(!isBatched)setRenderWorldList(new ArrayList([...global.soopyv2RenderWorldThings]));
return this;
}
stopRender(isBatched){
if(!canUseForgeRendering)return;
if(!global.soopyv2RenderWorldThings.has(this.javaObj))return this;
global.soopyv2RenderWorldThings.delete(this.javaObj);
if(!isBatched)setRenderWorldList(new ArrayList([...global.soopyv2RenderWorldThings]));
return this;
}}

class RenderHudAble{
startRender(){
if(!canUseForgeRendering)return;
if(global.soopyv2RenderHudThings.has(this.javaObj))return this;
global.soopyv2RenderHudThings.add(this.javaObj);
setRenderHudList(new ArrayList([...global.soopyv2RenderHudThings]));
return this;
}
stopRender(){
if(!canUseForgeRendering)return;
if(!global.soopyv2RenderHudThings.has(this.javaObj))return this;
global.soopyv2RenderHudThings.delete(this.javaObj);
setRenderHudList(new ArrayList([...global.soopyv2RenderHudThings]));
return this;
}}


export class Points extends RenderWorldAble{
constructor(points,r,g,b,a,thickness,depth){
this.javaObj=new RenderPointsC(new ArrayList(points.map((a)=>new Vec3(...a))),r,g,b,a,thickness,depth);
}

setPoints(points){
this.javaObj.points=new ArrayList(points.map((a)=>new Vec3(...a)));
return this;
}
setRGBA(r,g,b,a){
this.javaObj.red=r;
this.javaObj.green=g;
this.javaObj.blue=b;
this.javaObj.alpha=a;
return this;
}
setThickness(thickness){
this.javaObj.thickness=thickness;
return this;
}
setDepth(depth){
this.javaObj.depthtest=depth;
return this;
}
setDisableCullFace(disable){
this.javaObj.disableCullFace=disable;
return this;
}
setGLMode(glMode){
this.javaObj.glmode=glMode;
return this;
}}

export class FilledPoints extends Points{
constructor(points,r,g,b,a,thickness,depth){
super(points,r,g,b,a,thickness,depth);

this.setGLMode(GL11.GL_QUADS);
this.setDisableCullFace(true);
}}

export class Box extends Points{
constructor(location,size,r,g,b,a,thickness,depth){
super(Box.getPointsFromLocationSize(location,size),r,g,b,a,thickness,depth);
}

setLocationSize(location,size){
this.setPoints(Box.getPointsFromLocationSize(location,size));
return this;
}

static getPointsFromLocationSize(location,size){
let[x,y,z]=location;
let[width,height,width2]=size;

return[[x+width,y+height,z+width2],
[x+width,y+height,z],
[x,y+height,z],
[x,y+height,z+width2],
[x+width,y+height,z+width2],
[x+width,y,z+width2],
[x+width,y,z],
[x,y,z],
[x,y,z+width2],
[x,y,z],
[x,y+height,z],
[x,y,z],
[x+width,y,z],
[x+width,y+height,z],
[x+width,y,z],
[x+width,y,z+width2],
[x,y,z+width2],
[x,y+height,z+width2],
[x+width,y+height,z+width2]];
}}

export class FilledBox extends FilledPoints{
constructor(location,size,r,g,b,a,thickness,depth){
super(FilledBox.getPointsFromLocationSize(location,size),r,g,b,a,thickness,depth);
}

setLocationSize(location,size){
this.setPoints(FilledBox.getPointsFromLocationSize(location,size));
return this;
}

static getPointsFromLocationSize(location,size){
let[x,y,z]=location;
let[w,h,w2]=size;

return[
[x+w,y+0,z+w2],
[x+w,y+0,z],
[x,y+0,z],
[x,y+0,z+w2],

[x+w,y+h,z+w2],
[x+w,y+h,z],
[x,y+h,z],
[x,y+h,z+w2],

[x,y+h,z+w2],
[x,y+h,z],
[x,y+0,z],
[x,y+0,z+w2],

[x+w,y+h,z+w2],
[x+w,y+h,z],
[x+w,y+0,z],
[x+w,y+0,z+w2],

[x+w,y+h,z],
[x,y+h,z],
[x,y+0,z],
[x+w,y+0,z],

[x,y+h,z+w2],
[x+w,y+h,z+w2],
[x+w,y+0,z+w2],
[x,y+0,z+w2]];

}}

export class WorldText extends RenderWorldAble{
constructor(location,text,depth,scale){
this.javaObj=new RenderWorldTextC(new Vec3(...location),text,depth,scale);
}

setLocation(location){
this.javaObj.location=new Vec3(...location);
return this;
}
setText(text){
this.javaObj.text=text;
return this;
}
setDepthtest(depthtest){
this.javaObj.depthtest=depthtest;
return this;
}
setScale(scale){
this.javaObj.scale=scale;
return this;
}
setShadow(shadow){
this.javaObj.shadow=shadow;
return this;
}}


export class Beacon extends RenderWorldAble{
constructor(location,r,g,b,a,depth){
this.javaObj=new RenderBeaconC(new Vec3(...location),r,g,b,a,depth);
}

setLocation(location){
this.javaObj.location=new Vec3(...location);
return this;
}
setRGBA(r,g,b,a){
this.javaObj.red=r;
this.javaObj.green=g;
this.javaObj.blue=b;
this.javaObj.alpha=a;
return this;
}
setDepthtest(depthtest){
this.javaObj.depthtest=depthtest;
return this;
}}


export class HudPoints extends RenderHudAble{
constructor(points,r,g,b,a,thickness){
this.javaObj=new HudPointsC(new ArrayList(points.map((a)=>new Vector2f(...a))),r,g,b,a,thickness);
}

setPoints(points){
this.javaObj.points=new ArrayList(points.map((a)=>new Vec3(...a)));
return this;
}
setRGBA(r,g,b,a){
this.javaObj.colorR=r;
this.javaObj.colorG=g;
this.javaObj.colorB=b;
this.javaObj.colorA=a;
return this;
}
setThickness(thickness){
this.javaObj.thickness=thickness;
return this;
}
setGlmode(glmode){
this.javaObj.glmode=glmode;
return this;
}}

export class HudText extends RenderHudAble{
constructor(text,x,y,shadow){
this.javaObj=new HudTextC(text,x,y,shadow);
}

setText(text){
this.javaObj.textLines=text;
return this;
}
setX(x){
this.javaObj.x=x;
return this;
}
setY(y){
this.javaObj.y=y;
return this;
}
setScale(scale){
this.javaObj.scale=scale;
return this;
}
setShadow(shadow){
this.javaObj.shadow=shadow;
return this;
}}


export class Waypoint extends FilledBox{
constructor(x,y,z,r,g,b,{name="",showDist=!!name,phase=false}){
this.rendering=false;

let distToPlayerSq=(x-Player.getRenderX())**2+(y-(Player.getRenderY()+Player.getPlayer()["func_70047_e"]()))**2+(z-Player.getRenderZ())**2;

let alpha=Math.min(1,Math.max(0,1-(distToPlayerSq-10000)/12500));

super([x-0.001,y-0.001,z-0.001],[1.002,1.002,1.002],r,g,b,0.25*alpha,1,!phase);

this.params={x,y,z,r,g,b,name,showDist,phase};

this.outLine=new Box([x-0.002,y-0.002,z-0.002],[1.004,1.004,1.004],r,g,b,alpha,3,!phase);
this.beam=new Beacon([x,y+1,z],r,g,b,Math.min(1,Math.max(0,(distToPlayerSq-25)/100))*alpha,true);

let distToPlayer=Math.sqrt(distToPlayerSq);

let distRender=Math.min(distToPlayer,50);

let loc5=[Player.getRenderX()+(x+0.5-Player.getRenderX())/(distToPlayer/distRender),Player.getRenderY()+Player.getPlayer()["func_70047_e"]()+(y+2+20*distToPlayer/300-(Player.getRenderY()+Player.getPlayer()["func_70047_e"]()))/(distToPlayer/distRender),Player.getRenderZ()+(z+0.5-Player.getRenderZ())/(distToPlayer/distRender)];
let loc6=[Player.getRenderX()+(x+0.5-Player.getRenderX())/(distToPlayer/distRender),Player.getRenderY()+Player.getPlayer()["func_70047_e"]()+(y+2+20*distToPlayer/300-10*distToPlayer/300-(Player.getRenderY()+Player.getPlayer()["func_70047_e"]()))/(distToPlayer/distRender),Player.getRenderZ()+(z+0.5-Player.getRenderZ())/(distToPlayer/distRender)];

this.textLine1=new WorldText([loc5[0],loc5[1],loc5[2]],"\xA7a"+name,false,distRender/12);
this.textLine2=new WorldText([name?loc6[0]:loc5[0],name?loc6[1]:loc5[1],name?loc6[2]:loc5[2]],"\xA7b("+numberWithCommas(Math.round(distToPlayer))+"m)",false,distRender/12);
}

update(){
let{x,y,z,r,g,b,name,showDist}=this.params;

let distToPlayerSq=(x-Player.getRenderX())**2+(y-(Player.getRenderY()+Player.getPlayer()["func_70047_e"]()))**2+(z-Player.getRenderZ())**2;

let alpha=Math.min(1,Math.max(0,1-(distToPlayerSq-10000)/12500));

this.setRGBA(r,g,b,0.25*alpha);
this.outLine.setRGBA(r,g,b,alpha);
this.beam.setRGBA(r,g,b,Math.min(1,Math.max(0,(distToPlayerSq-25)/100))*alpha);

if(name||showDist){
let distToPlayer=Math.sqrt(distToPlayerSq);

let distRender=Math.min(distToPlayer,100);

let loc5=[Player.getRenderX()+(x+0.5-Player.getRenderX())/(distToPlayer/distRender),Player.getRenderY()+Player.getPlayer()["func_70047_e"]()+(y+2+20*distToPlayer/300-(Player.getRenderY()+Player.getPlayer()["func_70047_e"]()))/(distToPlayer/distRender),Player.getRenderZ()+(z+0.5-Player.getRenderZ())/(distToPlayer/distRender)];
let loc6=[Player.getRenderX()+(x+0.5-Player.getRenderX())/(distToPlayer/distRender),Player.getRenderY()+Player.getPlayer()["func_70047_e"]()+(y+2+20*distToPlayer/300-10*distToPlayer/300-(Player.getRenderY()+Player.getPlayer()["func_70047_e"]()))/(distToPlayer/distRender),Player.getRenderZ()+(z+0.5-Player.getRenderZ())/(distToPlayer/distRender)];

this.textLine1.setLocation([loc5[0],loc5[1],loc5[2]]).setScale(distRender/12);
this.textLine2.setLocation([name?loc6[0]:loc5[0],name?loc6[1]:loc5[1],name?loc6[2]:loc5[2]]).setScale(distRender/12).setText("\xA7b("+numberWithCommas(Math.round(distToPlayer))+"m)");
}
}

startRender(isBatched){
if(this.rendering)return this;
this.rendering=true;

super.startRender(true);
this.outLine.startRender(true);
this.beam.startRender(true);
if(this.params.name)this.textLine1.startRender(true);
if(this.params.showDist)this.textLine2.startRender(true);

if(!isBatched)setRenderWorldList(new ArrayList([...global.soopyv2RenderWorldThings]));
return this;
}

stopRender(isBatched){
if(!this.rendering)return this;
this.rendering=false;

super.stopRender(true);
this.outLine.stopRender(true);
this.beam.stopRender(true);
this.textLine1.stopRender(true);
this.textLine2.stopRender(true);

if(!isBatched)setRenderWorldList(new ArrayList([...global.soopyv2RenderWorldThings]));
return this;
}}


register("worldLoad",()=>{
if(!net.minecraftforge.fml.common.Loader.isModLoaded("soopyv2forge")){
ChatLib.chat("&1"+ChatLib.getChatBreak("-").trim());
ChatLib.chat("\xA7cWARNING: You dont have the forge mod for soopyv2 installed");
ChatLib.chat("\xA7cWARNING: -> almost nothing can be rendered");
new TextComponent(" &e[CLICK] &7- Download").setHover("show_text","&2Download").setClick("open_url","https://github.com/Soopyboo32/SoopyV2Forge/releases").chat();
ChatLib.chat("Or if u want to remove soopyv2 run /ct delete soopyv2");
ChatLib.chat("&1"+ChatLib.getChatBreak("-").trim());
}
if(SoopyV2Forge.getVersion()!==LASTEST_SOOPYFORGE_VER){
ChatLib.chat("&1"+ChatLib.getChatBreak("-").trim());
ChatLib.chat("\xA7cWARNING: Your forge version of soopyv2 is outdated");
if(LASTEST_SOOPYFORGE_VER==="1.1"){
ChatLib.chat("\xA7cWARNING: this does not affect much at the moment, but has an incorect download url");
}else{
ChatLib.chat("\xA7cWARNING: -> almost nothing can be rendered");
}
new TextComponent(" &e[CLICK] &7- Download").setHover("show_text","&2Download update").setClick("open_url","https://github.com/Soopyboo32/SoopyV2Forge/releases").chat();
ChatLib.chat("&1"+ChatLib.getChatBreak("-").trim());
}
});

if(addFix){
global.soopyV2RenderfixLineThing=new Box([-1000000000,0,0],0,0,0,0,0,1,false);
}