


import Feature from"../../featureClass/class";
import{drawBoxAtBlock,drawBoxAtBlock2,drawFilledBox,drawLine,drawLinePoints}from"../../utils/renderUtils";
import{calculateDistanceQuick}from"../../utils/utils";
import SettingBase from"../settings/settingThings/settingBase";
import ButtonSetting from "../settings/settingThings/button";

const EntityItem=Java.type("net.minecraft.entity.item.EntityItem");

const EnumParticleTypes=Java.type("net.minecraft.util.EnumParticleTypes");

class DungeonRoutes extends Feature{
constructor(){
super();
}

onEnable(){
//if(Player.getUUID().toString()!=="dc8c3964-7b29-4e03-ae9e-d13ebd65dd29"){
		new ButtonSetting("Released in Badlion", "will NOT be coming to SoopyV2", "badlion_routes_button", this, "Download", () => {
            java.awt.Desktop.getDesktop().browse(
                new java.net.URI("https://www.badlion.net/?utm_source=SoopyIngame&utm_medium=web&utm_campaign=brand_awareness"));
		}, false)
return;
//}

this.recordingData=[];
this.currentActionIndex=0;
this.lastLocationUpdatedTime=Date.now();

this.registerEvent("soundPlay",this.playSound);
this.registerEvent("worldLoad",this.worldLoad);
this.registerEvent("playerInteract",this.playerInteract);
this.registerForge(net.minecraftforge.event.entity.EntityJoinWorldEvent,this.entityJoinWorldEvent);
let packetRecieved=this.registerCustom("packetReceived",this.pickupItem);

try{
packetRecieved.trigger.setPacketClasses([net.minecraft.network.play.server.S0DPacketCollectItem]);
}catch(e){}

this.registerStep(true,5,()=>{
let roomId=this.getCurrentRoomId();
if(this.lastRoomId!==roomId){
this.lastRoomId=roomId;
this.recordingData=[];

this.currRoomData=this.getRoomWorldData();

this.currentRouteDisplay=this.routesIndexMap.get(this.fullRoomData[this.idMap.get(roomId)].index)?.data;
ChatLib.chat(JSON.stringify(this.currentRouteDisplay,undefined,2));
}

if(!this.recordRoute)return;
if(!this.recordingData[this.recordingData.length-1])return;
let locs=this.recordingData[this.recordingData.length-1].locations;
if(locs.length===0||
Math.ceil(Player.getX())!==locs[locs.length-1][0]||
Math.ceil(Player.getY())!==locs[locs.length-1][1]||
Math.ceil(Player.getZ())!==locs[locs.length-1][2]){

this.addRecordingPoint("locations",[Math.ceil(Player.getX()),Math.ceil(Player.getY()),Math.ceil(Player.getZ())]);
}
});

this.registerEvent("renderWorld",()=>{
if(this.recordingData&&this.recordingData[this.recordingData.length-1]){
this.recordingData[this.recordingData.length-1].etherwarps.forEach((loc)=>{
drawFilledBox(loc[0],loc[1]-1,loc[2],1,1,1,0,0,50/255,true);
drawBoxAtBlock(loc[0]-0.5,loc[1]-1,loc[2]-0.5,1,0,0,1,1,1);
});
this.recordingData[this.recordingData.length-1].mines.forEach((loc)=>{
drawFilledBox(loc[0],loc[1]-0.5,loc[2],1,1,0,1,0,50/255,true);
});
this.recordingData[this.recordingData.length-1].tnts.forEach((loc)=>{
drawFilledBox(loc[0],loc[1]-0.5,loc[2],1,1,1,0,0,50/255,true);
});
this.recordingData[this.recordingData.length-1].interacts.forEach((data)=>{
let loc=data.loc;
drawFilledBox(loc[0],loc[1],loc[2],1,1,0,0,1,50/255,true);
drawBoxAtBlock(loc[0]-0.5,loc[1],loc[2]-0.5,0,0,1,1,1,1);
});
let locs=this.recordingData[this.recordingData.length-1].locations;
if(locs.length>=2)drawLinePoints(locs.map((a)=>[a[0]-0.5,a[1]+0.1,a[2]-0.5]),0,0,255,2,false);
}

if(this.currRoomData){
if(this.currentRouteDisplay){
this.currentRouteDisplay[this.currentActionIndex].etherwarps.forEach((loc)=>{
let coords=this.toRoomCoordinates(loc[0],loc[1]-1,loc[2]);
drawFilledBox(coords[0],coords[1],coords[2],1,1,1,0,0,50/255,true);
drawBoxAtBlock(coords[0]-0.5,coords[1],coords[2]-0.5,1,0,0,1,1,1);
});
this.currentRouteDisplay[this.currentActionIndex].mines.forEach((loc)=>{
let coords=this.toRoomCoordinates(loc[0],loc[1]-0.5,loc[2]);
drawBoxAtBlock(coords[0]-0.5,coords[1],coords[2]-0.5,1,1,0,1,1,50/255);
});
this.currentRouteDisplay[this.currentActionIndex].tnts.forEach((loc)=>{
let coords=this.toRoomCoordinates(loc[0],loc[1]-1,loc[2]);
drawBoxAtBlock(coords[0]-0.5,coords[1]+0.5,coords[2]-0.5,1,1,255,1,1,50/255);
});
this.currentRouteDisplay[this.currentActionIndex].interacts.forEach((data)=>{
let coords=this.toRoomCoordinates(data.loc[0],data.loc[1],data.loc[2]);
drawFilledBox(coords[0],coords[1],coords[2],1,1,0,0,1,50/255,true);
drawBoxAtBlock(coords[0]-0.5,coords[1],coords[2]-0.5,0,0,1,1,1,1);
});



}
}

});

this.tempItemIdLocs=new Map;

this.idMap=new Map;
this.routesIndexMap=new Map;
this.fullRoomData=JSON.parse(FileLib.read("SoopyV2","data/roomdata.json"));
this.fullRoutesData=JSON.parse(FileLib.read("SoopyV2","features/dungeonRoutes/routesData.json"));
this.fullRoomData.forEach((d,i)=>{
d.id.forEach((id)=>{
this.idMap.set(id,i);
});
this.idMap.set(d.index,i);
});
this.fullRoutesData.forEach((d,i)=>{
this.routesIndexMap.set(d.index,d);
});
this.lastRoomId=undefined;

this.currRoomData=undefined;
this.currentRouteDisplay=undefined;

this.registerCommand("roomid",(...name)=>{
ChatLib.chat(JSON.stringify(this.getCurrentRoomData(),undefined,2));
ChatLib.chat(JSON.stringify(this.getRoomWorldData(),undefined,2));
});
this.recordRoute=false;

this.registerCommand("startroute",(...name)=>{
this.recordRoute=true;
this.recordingData=[];
this.addRecordingPoint();
ChatLib.chat(this.FeatureManager.messagePrefix+"Started recording route!");
});

this.registerCommand("saveroute",()=>{
let data={
index:this.fullRoomData[this.idMap.get(this.lastRoomId)].index,
data:this.recordingData.map((a)=>{
a.etherwarps=a.etherwarps.map((a)=>this.fromRoomCoordinates(a[0],a[1],a[2]));
a.mines=a.mines.map((a)=>this.fromRoomCoordinates(a[0],a[1],a[2]));
a.locations=a.locations.map((a)=>this.fromRoomCoordinates(...a));
a.interacts=a.interacts.map((b)=>{
b.loc=this.fromRoomCoordinates(...b.loc);
return b;
});
a.tnts=a.tnts.map((a)=>this.fromRoomCoordinates(a[0],a[1],a[2]));

return a;
})};









ChatLib.chat(JSON.stringify(data,undefined,4));
ChatLib.chat(this.FeatureManager.messagePrefix+"Saved route!");
this.recordRoute=false;
});

this.registerStep(true,5,()=>{
if(this.currRoomData){
if(this.currentRouteDisplay){

if(this.currentRouteDisplay[this.currentActionIndex].locations.length>=2)this.drawLineMultipleParticles(this.currentRouteDisplay[this.currentActionIndex].locations.map((a)=>this.toRoomCoordinates(a[0],a[1],a[2])));

}
}
});
}

addRecordingPoint(type,point){
if(type){
this.recordingData[this.recordingData.length-1][type].push(point);
}
if(!type||type==="interacts"){
this.recordingData.push({
etherwarps:[],
mines:[],
locations:[],
interacts:[],
tnts:[]});

}
}
drawLineMultipleParticles(locations){
let lastLoc=undefined;
locations.forEach((loc)=>{
if(!lastLoc){
lastLoc=loc;
return;
}

this.drawLineParticles(lastLoc,loc);
lastLoc=loc;
});
}

drawLineParticles(loc1,loc2){
let distance=Math.hypot(...loc1.map((a,i)=>a-loc2[i]));
let maxPoints=Math.ceil(distance*1);
for(let i=0;i<maxPoints;i++){
let actualI=i+Math.random();
let a=actualI/maxPoints;
let loc=[loc1[0]*a+loc2[0]*(1-a)-0.5,loc1[1]*a+loc2[1]*(1-a)+0.1,loc1[2]*a+loc2[2]*(1-a)-0.5];

let a2=(actualI+0.02)/maxPoints;
let loc3=[loc1[0]*a2+loc2[0]*(1-a2)-0.5,loc1[1]*a2+loc2[1]*(1-a2)+0.1,loc1[2]*a2+loc2[2]*(1-a2)-0.5];
loc3=loc3.map((a,i)=>loc[i]-a);

this.spawnParticleAtLocation(loc,loc3,"FLAME");
}
}

spawnParticleAtLocation(loc,velo,particle){
let particleType=EnumParticleTypes.valueOf(particle);
let idField=particleType.getClass().getDeclaredField("field_179372_R");
idField.setAccessible(true);
let id=idField.get(particleType);

Client.getMinecraft().field_71438_f.func_174974_b(
id,
true,
loc[0],
loc[1],
loc[2],
velo[0],
velo[1],
velo[2]);

}

toRoomCoordinates(x,y,z){
if(!this.currRoomData)return null;

if(this.currRoomData.rotation===2){
z*=-1;
[x,z]=[z,x];
}else if(this.currRoomData.rotation===3){
x*=-1;
z*=-1;
}else if(this.currRoomData.rotation===4){
x*=-1;
[x,z]=[z,x];
}

return[this.currRoomData.cx+x,y,this.currRoomData.cy+z];
}
fromRoomCoordinates(x,y,z){
if(!this.currRoomData)return null;

x-=this.currRoomData.cx;
z-=this.currRoomData.cy;

if(this.currRoomData.rotation===2){
[x,z]=[z,x];
z*=-1;
}else if(this.currRoomData.rotation===3){
x*=-1;
z*=-1;
}else if(this.currRoomData.rotation===4){
[x,z]=[z,x];
x*=-1;
}

return[x,y,z];
}

getRotation(x,y,width,height,roofY){
let currRoomData=this.getCurrentRoomData();
if(!currRoomData)return-1;

if(currRoomData.shape!=="L"){
if(this.getTopBlockAt(x,y,roofY)===11)return 1;
if(this.getTopBlockAt(x+width,y,roofY)===11)return 2;
if(this.getTopBlockAt(x+width,y+height,roofY)===11)return 3;
if(this.getTopBlockAt(x,y+height,roofY)===11)return 4;
}else{
let one=this.getTopBlockAt2(x+width/2+1,y+height/2,roofY);
let two=this.getTopBlockAt2(x+width/2-1,y+height/2,roofY);
let three=this.getTopBlockAt2(x+width/2,y+height/2+1,roofY);
let four=this.getTopBlockAt2(x+width/2,y+height/2-1,roofY);

if(one===0&&three===0)return 1;
if(two===0&&three===0)return 2;
if(one===0&&four===0)return 3;
if(two===0&&four===0)return 4;
}

return-1;
}

getRoomWorldData(){
let x=Math.floor((Player.getX()+8)/32)*32-8;
let y=Math.floor((Player.getZ()+8)/32)*32-8;
let width=30;
let height=30;

let roofY=this.getRoofAt(x,y);

while(World.getBlockStateAt(new BlockPos(x-1,roofY,y)).getBlockId()!==0){
x-=32;
width+=32;
}
while(World.getBlockStateAt(new BlockPos(x,roofY,y-1)).getBlockId()!==0){
y-=32;
height+=32;
}
while(World.getBlockStateAt(new BlockPos(x-1,roofY,y)).getBlockId()!==0){
x-=32;
width+=32;
}
while(World.getBlockStateAt(new BlockPos(x+width+1,roofY,y)).getBlockId()!==0){
width+=32;
}
while(World.getBlockStateAt(new BlockPos(x,roofY,y+height+1)).getBlockId()!==0){
height+=32;
}
while(World.getBlockStateAt(new BlockPos(x+width,roofY,y+height+1)).getBlockId()!==0){
height+=32;
}
while(World.getBlockStateAt(new BlockPos(x+width+1,roofY,y+height)).getBlockId()!==0){
width+=32;
}
while(World.getBlockStateAt(new BlockPos(x+width,roofY,y-1)).getBlockId()!==0){
y-=32;
height+=32;
}
while(World.getBlockStateAt(new BlockPos(x-1,roofY,y+height)).getBlockId()!==0){
x-=32;
width+=32;
}


return{
x,
y,
width,
height,
cx:x+width/2,
cy:y+height/2,
rotation:this.getRotation(x,y,width,height,roofY)};

}

getRoofAt(x,z){
let y=255;
while(y>0&&World.getBlockStateAt(new BlockPos(x,y,z)).getBlockId()===0)y--;

return y;
}

getTopBlockAt(x,z,y){
if(!y)y=this.getHeightAt(x,z);

return World.getBlockStateAt(new BlockPos(x,y,z)).getMetadata();
}
getTopBlockAt2(x,z,y){
if(!y)y=this.getHeightAt(x,z);

return World.getBlockStateAt(new BlockPos(x,y,z)).getBlockId();
}

getCurrentRoomData(){
let roomId=this.idMap.get(this.getCurrentRoomId());
if(roomId===undefined)return null;

return this.fullRoomData[roomId];
}

getCurrentRoomId(){
let id=Scoreboard.getLineByIndex(Scoreboard.getLines().length-1).getName().trim().split(" ").pop();

return id;
}

worldLoad(){

}

entityJoinWorldEvent(event){
if(event.entity instanceof EntityItem){

let e=new Entity(event.entity);
let pos=[e.getX(),e.getY(),e.getZ()];

this.tempItemIdLocs.set(event.entity["func_145782_y"](),pos);

}
}

pickupItem(packet){
let packetType=new String(packet.class.getSimpleName()).valueOf();
if(packetType==="S0DPacketCollectItem"){
let pos=this.tempItemIdLocs.get(packet["func_149354_c"]());

let data=this.currentRouteDisplay[this.currentActionIndex].interacts[0];
if(data&&data.type==="item"){
let coords=this.toRoomCoordinates(data.loc[0],data.loc[1],data.loc[2]);
if(calculateDistanceQuick(pos,coords)<2){
if(this.currentRouteDisplay.length>=this.currentActionIndex){
this.currentActionIndex++;
}
}
}

if(!this.recordRoute)return;
if(pos)this.addRecordingPoint("interacts",{loc:pos,type:"item"});
}
}

playerInteract(action,position,event){
if(action.toString()!=="RIGHT_CLICK_BLOCK")return;

let pos=[Player.lookingAt().getX()+0.5,Player.lookingAt().getY(),Player.lookingAt().getZ()+0.5];

let id=Player.lookingAt().getType().getID();
if(id!==54&&id!==144&&id!==69)return;


let data=this.currentRouteDisplay[this.currentActionIndex].interacts[0];
if(data&&data.type==="interact"){
let coords=this.toRoomCoordinates(data.loc[0],data.loc[1],data.loc[2]);
console.log(coords.join(","),pos.join(","));
if(coords.join(",")===pos.join(",")){
if(this.currentRouteDisplay.length>this.currentActionIndex){
this.currentActionIndex++;
}
}
}

if(!this.recordRoute)return;
this.addRecordingPoint("interacts",{loc:pos,type:"interact"});
}

playSound(pos,name,volume,pitch,categoryName,event){
if(!this.recordRoute)return;

let loc=[pos.x,pos.y,pos.z];
let nameSplitted=name.split(".");
if(name==="mob.enderdragon.hit"){
this.addRecordingPoint("etherwarps",loc);
}
if(name==="random.explode"&&pitch!==1){
this.addRecordingPoint("tnts",loc);
}
if(name==="mob.bat.death"){
this.addRecordingPoint("interacts",{loc:loc,type:"bat"});
}
if(nameSplitted[0]==="dig"){
if(!this.recordingData[this.recordingData.length-1].mines.some((a)=>
a[0]===pos[0]&&
a[1]===pos[1]&&
a[2]===pos[2]))
{
this.addRecordingPoint("mines",loc);
}
}
}

onDisable(){

}}



module.exports={
class:new DungeonRoutes};