

import SoopyNumber from"../../../guimanager/Classes/SoopyNumber";
import Feature from"../../featureClass/class";

import LocationSetting from"../settings/settingThings/location";
import ToggleSetting from"../settings/settingThings/toggle";
import HudTextElement from"./HudTextElement";
import DropdownSetting from"../settings/settingThings/dropdownSetting";
import{getLevelByXp}from"../../utils/statUtils";
import{firstLetterCapital}from"../../utils/stringUtils";
import renderLibs from"../../../guimanager/renderLibs";
import{addNotation,basiclyEqual,numberWithCommas,timeNumber,timeNumber2}from"../../utils/numberUtils.js";
import{formatTime,getLore}from"../../utils/utils";
const ProcessBuilder=Java.type("java.lang.ProcessBuilder");
const Scanner=Java.type("java.util.Scanner");



let fishingExp={"A Squid appeared.":41,"You caught a Sea Walker.":68,"Pitch Darkness reveals you've caught a Night Squid.":270,"You stumbled upon a Sea Guardian.":101,"It looks like you've disrupted the Sea Witch's brewing session. Watch out, she's furious!":338,"You reeled in a Sea Archer.":169,"The Monster of The Deep emerges from the dark depths...":270,"Huh? A Catfish!":405,"Gross! A Sea Leech!":675,"You've discovered a Guardian Defender of the sea.":1013,"You have awoken the Deep Sea Protector, prepare for a battle!":1350,"The Water Hydra has come to test your Strength.":4050,"The Sea Emperor arises from the depths...":3375,"A Water Worm surfaces!":240,"A Poisoned Water Worm surfaces!":270,"A flaming worm surfaces from the depths!":240,"A Lava Blaze has surfaced from the depths!":548,"A Lava Pigman arose from the depths!":568,"A Zombie Miner surfaces!":770,"From Beneath the lava":730,"You hear a faint Moo":950,"A small but fearsome":1400,"You feel the heat":1100,"A Lava Flame flies out from beneath the lava.":2100,"A Fire Eel slithers out":2200,"Taurus and his steed emerge.":4300,"You hear a massive rumble as Thunder emerges.":12000,"You have angered a legendary creature... ":40000,"WOAH! A Plhlegblast appeared.":5000,"Phew! It's only a scarecrow.":420,"You hear trotting from beneath the waves, you caught a Nightmare":820,"It must be a full moon, it's a Werewolf!":1235,"The spirit of a long lost Phantom Fisher has come to haunt you.":2525,"[[Frozen Steve]] fell into the pond long ago, never to resurface... until now!":101,"Its a Snowman! It looks harmless.":203,"The Grinch stole [[Jerry]]'s [[Gifts]]...get them back!":405,"What is this creature!?":4050,"A tiny fin emerges from the water, you've caught a Nurse Shark.":405,"You spot a fin as blue as the water it came from, it's a Blue Shark.":810,"A striped beast bounds from the depths, the wild Tiger Shark!":1013,"Hide no longer, a Great White Shark has tracked your scent and thirsts for your blood!":2025};

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

initVariables(){

this.hudElements=[];

this.fpsElement=undefined;
this.cpsElement=undefined;
this.soulflowElement=undefined;
this.petElement=undefined;
this.fpsEnabledSetting=undefined;
this.cpsEnabledSetting=undefined;
this.soulflowEnabledSetting=undefined;
this.soulflowShowWarningSetting=undefined;
this.soulflowShowWhen0Setting=undefined;
this.petEnabledSetting=undefined;
this.fpsFastSetting=undefined;
this.fpsLowSetting=undefined;
this.cpsSeperate=undefined;
this.cpsIncludeRight=undefined;

this.petLevels=undefined;

this.lastTickTime=undefined;
this.framesSince=undefined;
this.lastframe=undefined;
this.Instant=undefined;

this.lastFrameRates=undefined;

this.fps=undefined;
this.lowFps=undefined;

this.slowestFrameTime=undefined;
this.lastFrameRatesS=undefined;
this.numberUtils=undefined;

this.petText=undefined;

this.lastWitherImpact=undefined;
this.aup=undefined;
this.lastTickEventEpochTimestamp=undefined;
this.lastAbsorbtion=undefined;
this.impactTest=undefined;
}

onEnable(){
this.initVariables();

this.numberUtils=require("../../utils/numberUtils.js");

this.fpsEnabledSetting=new ToggleSetting("Fps enabled","Whether the fps is rendered onto the screen",true,"fps_enabled",this);
this.fpsFastSetting=new ToggleSetting("Fast fps update","Whether the fps is updated fast instead of once per second",true,"fps_fast",this).requires(this.fpsEnabledSetting);
this.fpsLowSetting=new ToggleSetting("Low fps display","Display the minumum frame time next to fps (usefull for finding framedrops)",true,"fps_low",this).requires(this.fpsFastSetting);

this.fpsElement=new HudTextElement().
setToggleSetting(this.fpsEnabledSetting).
setLocationSetting(new LocationSetting("Show FPS","Allows you to edit the location of the fps text","fps_location",this,[10,10,1,1]).
requires(this.fpsEnabledSetting));
this.hudElements.push(this.fpsElement);

this.cpsEnabledSetting=new ToggleSetting("Show CPS","Whether the cps is rendered onto the screen",true,"cps_enabled",this);
this.cpsIncludeRight=new ToggleSetting("CPS include right click","Whether right clicks are shown in the CPS",true,"cps_right",this).requires(this.cpsEnabledSetting);
this.cpsSeperate=new ToggleSetting("CPS seperate right","Seperates right clicks from left clicks",true,"cps_seperate",this).requires(this.cpsIncludeRight);

this.cpsElement=new HudTextElement().
setToggleSetting(this.cpsEnabledSetting).
setLocationSetting(new LocationSetting("Cps Location","Allows you to edit the location of the cps text","cps_location",this,[10,20,1,1]).
requires(this.cpsEnabledSetting));
this.hudElements.push(this.cpsElement);

this.petEnabledSetting=new ToggleSetting("Show Current Pet","Whether the current pet is rendered onto the screen",true,"pet_enabled",this);
this.petElement=new HudTextElement().
setToggleSetting(this.petEnabledSetting).
setLocationSetting(new LocationSetting("Pet Location","Allows you to edit the location of the pet text","pet_location",this,[10,30,1,1]).
requires(this.petEnabledSetting).
editTempText("&6Pet&7> &7[Lvl 100] &aEnderman"));
this.hudElements.push(this.petElement);
this.scanGuiForPet=new ToggleSetting("Scan pets menu gui for selected pet","Only disable if you get a lot of lag in the pets menu",true,"scan_pets_menu",this).requires(this.petEnabledSetting);

this.locationEnabledSetting=new ToggleSetting("Show Location","Whether the location (xyz) is rendered onto the screen",false,"location_enabled",this);
this.locationElement=new HudTextElement().
setToggleSetting(this.locationEnabledSetting).
setLocationSetting(new LocationSetting("XYZ Location","Allows you to edit the location of the location text","location_location",this,[10,120,1,1]).
requires(this.locationEnabledSetting).
editTempText("&6Loc&7> &f123.456 | 123.456 | 123.456"));
this.hudElements.push(this.locationElement);
this.locationYEnabledSetting=new ToggleSetting("Show Y in location","Wether to include ur Y value in location",true,"location_y_enabled",this).requires(this.locationEnabledSetting);
this.locationOnlyDungSetting=new ToggleSetting("Only show location in dungeon","(If u want to use this to show how to mine thru stairs)",false,"location_dung_enabled",this).requires(this.locationEnabledSetting);
this.locationDecimals=new DropdownSetting("Decimal places in location setting","","3","location_decimal_setting",this,{
"0":"0",
"1":"1",
"2":"2",
"3":"3",
"4":"4"}).
requires(this.locationEnabledSetting);

this.soulflowEnabledSetting=new ToggleSetting("Show Soulflow","Whether the soulflow count is rendered onto the screen",true,"soulflow_enabled",this);
this.soulflowShowWhen0Setting=new ToggleSetting("Show When 0 Soulflow","If this is off it wont render when you have 0 soulflow",true,"soulflow_showwhen_0",this).requires(this.soulflowEnabledSetting);
this.soulflowElement=new HudTextElement().
setToggleSetting(this.soulflowEnabledSetting).
setLocationSetting(new LocationSetting("Soulflow Location","Allows you to edit the location of the soulflow text","soulflow_location",this,[10,40,1,1]).
requires(this.soulflowEnabledSetting).
editTempText("&6Soulflow&7> &f12,345"));
this.hudElements.push(this.soulflowElement);

this.lagEnabled=new ToggleSetting("Show Lobby TPS","Calculates the TPS of your current lobby (20=no lag)",true,"lobby_lag",this);
this.lagElement=new HudTextElement().
setToggleSetting(this.lagEnabled).
setLocationSetting(new LocationSetting("Lobby TPS Location","Allows you to edit the location of the TPS","lobby_lag_location",this,[10,60,1,1]).
requires(this.lagEnabled).
editTempText("&6Tps&7> &f20.0"));
this.hudElements.push(this.lagElement);

this.witherImpactCooldownSetting=new ToggleSetting("Show Wither Impact Cooldown","This will render a small cooldown above your crosshair",true,"wither_impact_cooldown_enabled",this);



this.showSpotifyPlaying=new ToggleSetting("Show Current Playing Spotify Song","(WINDOWS + Spotify Desktop only)",false,"spotify_now_playing",this);
this.spotifyElement=new HudTextElement().
setText("&6Spotify&7> ").
setBaseEditWidth(Renderer.getStringWidth("Spotify> ")+150).
setToggleSetting(this.showSpotifyPlaying).
setLocationSetting(new LocationSetting("Spotify Location","Allows you to edit the location of the spotify text","spotify_now_playing_location",this,[10,80,1,1]).
requires(this.showSpotifyPlaying).
editTempText("&6Spotify&7> &cNot open"));
this.hudElements.push(this.spotifyElement);
this.spotifyElement2=new HudTextElement().setLocationSetting({
setParent:()=>{},
x:this.spotifyElement.locationSetting.x+this.spotifyElement.getWidth(),
y:this.spotifyElement.locationSetting.y,
scale:this.spotifyElement.locationSetting.scale,
shadowType:this.spotifyElement.locationSetting.shadowType});

this.spotifyElement2.disableRendering();

this.showLobbyDay=new ToggleSetting("Show Current Lobby Day","",true,"lobby_day",this);
this.lobbyDayElement=new HudTextElement().
setText("&6Day&7> &fLoading...").
setToggleSetting(this.showLobbyDay).
setLocationSetting(new LocationSetting("Lobby Day Location","Allows you to edit the location of the lobby day","lobby_day_location",this,[10,90,1,1]).
requires(this.showLobbyDay).
editTempText("&6Day&7> &f5.15"));
this.showLobbyDayOnlyUnder30=new ToggleSetting("Show Current Lobby Day ONLY WHEN under day 30","",true,"lobby_day_30",this);
this.hudElements.push(this.lobbyDayElement);

let hudStatTypes={
"cata":"Catacombs level + Exp",
"totaldeaths":"Total deaths"};


this.skillLevelCaps={
"experience_skill_combat":60,
"experience_skill_foraging":50,
"experience_skill_farming":60,
"experience_skill_fishing":50,
"experience_skill_alchemy":50,
"experience_skill_enchanting":60,
"experience_skill_mining":60,
"experience_skill_taming":50,
"experience_skill_carpentry":50};


this.lastSkillLevel={
"experience_skill_combat":undefined,
"experience_skill_foraging":undefined,
"experience_skill_farming":undefined,
"experience_skill_fishing":undefined,
"experience_skill_alchemy":undefined,
"experience_skill_enchanting":undefined,
"experience_skill_mining":undefined,
"experience_skill_taming":undefined,
"experience_skill_carpentry":undefined};


this.spotifyProcessId=-1;

Object.keys(this.skillLevelCaps).forEach((skill)=>{
hudStatTypes[skill]=firstLetterCapital(skill.split("_").pop())+" level + Exp";
});

hudStatTypes.completions_enterance="Enterance completions";
for(let i=1;i<8;i++){
hudStatTypes["completions_floor_"+i]="Floor "+i+" completions";
}
for(let i=1;i<8;i++){
hudStatTypes["completions_master_"+i]="Master "+i+" completions";
}
for(let i=1;i<8;i++){
hudStatTypes["completions_dungeon_"+i]="Dungeon "+i+" completions";
}


hudStatTypes["mythril_powder"]="Mithril Powder";
hudStatTypes["gemstone_powder"]="Gemstone Powder";

this.potsExpireAt={};

this.potsOutAlert=new ToggleSetting("Alert when pots are about to run out","Will show in chat",true,"pots_out_alert",this);
this.showPotsHud=new ToggleSetting("Show Pots On Hud","",false,"pots_hud",this);
this.potsHudElement=new HudTextElement().
setText("&6Potions&7> &fLoading...").
setToggleSetting(this.showPotsHud).
setLocationSetting(new LocationSetting("Pots Hud Location","Allows you to edit the location of the pots hud","pots_hud_location",this,[10,100,1,1]).
requires(this.showPotsHud).
editTempText("&6God potion&7> &f28h 32m"));
this.hudElements.push(this.potsHudElement);

this.lastPotAlerts={};
this.registerStep(false,1,this.updatePotsTime);

this.extendLevelCap=new ToggleSetting("Hud Stat Ignore Skill Level Cap","level cap goes over 60 requiring 50m xp per level",false,"hud_ignore_level_cap",this).contributor("EmeraldMerchant");
this.showLevelUpMessage=new ToggleSetting("Show level-up message","Shows skyblock skills level-up message over level 60 in chat",true,"skill_o60_level_message",this).requires(this.extendLevelCap).contributor("EmeraldMerchant");

this.hudStat=[];
for(let i=0;i<5;i++){
this.hudStat[i]={};
this.hudStat[i].enabled=new ToggleSetting("Hud Stat Slot #"+(i+1),"Allows you to render a custom stat on your hud",false,"hud_stat_"+i,this);
this.hudStat[i].type=new DropdownSetting("Hud Stat Slot #"+(i+1)+" Type","The type of stat to render","weight","hud_stat_"+i+"_type",this,hudStatTypes);
this.hudStat[i].location=new LocationSetting("Hud Stat Slot #"+(i+1)+" Location","Allows you to edit the location of the hud stat","hud_stat_"+i+"_location",this,[10,50+i*10,1,1]).editTempText("&6Hud Stat&7> &f12,345");
this.hudStat[i].textElement=new HudTextElement().setToggleSetting(this.hudStat[i].enabled).setLocationSetting(this.hudStat[i].location).setText("&6Hud Stat&7> &fLoading...");
this.hudStat[i].onlySb=new ToggleSetting("Hud Stat Slot #"+(i+1)+" Only SB","Only render this stat when you are in skyblock",true,"hud_stat_"+i+"_only_sb",this).requires(this.hudStat[i].enabled);

this.hudStat[i].location.requires(this.hudStat[i].enabled);
this.hudStat[i].type.requires(this.hudStat[i].enabled);
if(this.hudStat[i-1]){
this.hudStat[i].enabled.requires(this.hudStat[i-1].enabled);
}
this.hudElements.push(this.hudStat[i].textElement);
}


this.showDragonDamages=new ToggleSetting("Show dragon damages","This will render the top 3 damages + your damage during a dragon fight",true,"dragon_dmg_enable",this);
this.dragonDamageElement=new HudTextElement().
setToggleSetting(this.showDragonDamages).
setLocationSetting(new LocationSetting("Damage Location","Allows you to edit the location of the damage leaderboard","dragon_dmg_location",this,[50,40,1,1]).
requires(this.showDragonDamages).
editTempText("&6Old Dragon &7(&f13.4&7M HP)\n&7- &fSoopyboo32&7:&f 13.4&7M\n&7- &fCamCamSatNav&7:&f 12.3&7M\n&7- &fMuffixy&7:&f 3.4&7M"));
this.hudElements.push(this.dragonDamageElement);


this.showThunderingTimer=new ToggleSetting("Spider den thundering timer","",true,"spider_thundering_timer",this);
this.thunderTimerElement=new HudTextElement().
setToggleSetting(this.showThunderingTimer).
setLocationSetting(new LocationSetting("Thunder timer element","Allows you to edit the location of the thunder timer","thunder_timer_elmement",this,[10,70,1,1]).
requires(this.showThunderingTimer));
this.hudElements.push(this.thunderTimerElement);

this.showRain=new ToggleSetting("Spider den RAIN timer","",false,"spider_rain_timer",this).requires(this.showThunderingTimer);

this.ppsCounter=new ToggleSetting("Packets/second","debug not really usefull",false,"pps_counter",this);
this.ppsCounterElement=new HudTextElement().
setToggleSetting(this.ppsCounter).
setLocationSetting(new LocationSetting("Packets/second location","Allows you to edit the location of the pps","pps_location",this,[10,70,1,1]).
requires(this.ppsCounter));
this.hudElements.push(this.ppsCounterElement);

this.packetsSent=0;
this.packetsRecieved=0;

this.registerEvent("packetReceived",(p)=>{
this.packetsRecieved++;

}).registeredWhen(()=>this.ppsCounter.getValue());

this.registerEvent("packetSent",(p)=>{
this.packetsSent++;

}).registeredWhen(()=>this.ppsCounter.getValue());

this.step_5second();

this.lastTickTime=0;
this.framesSince=0;
this.lastframe=0;
this.slowestFrameTime=0;

this.lastSwappedPet=0;

this.lastWitherImpact=0;
this.aup=0;
this.lastTickEventEpochTimestamp=0;
this.lastAbsorbtion=0;
this.impactTest=false;
this.apiSoulflow=false;

this.lastUpdatedStatData=0;

this.lastStatData=undefined;

this.lastFrameRates=[0,0,0,0,0,0,0,0,0,0];
this.lastFrameRatesS=[0,0,0,0,0,0,0,0,0,0];

this.Instant=Java.type("java.time.Instant");

this.fps=new SoopyNumber(0);
this.lowFps=new SoopyNumber(0);

this.registerEvent("renderOverlay",this.renderHud).registeredWhen(()=>this.showSpotifyPlaying.getValue()||this.witherImpactCooldownSetting.getValue());
this.registerStep(true,5,this.step);
this.registerStep(false,5,this.step_5second);
this.registerEvent("renderWorld",this.renderWorld).registeredWhen(()=>this.fpsEnabledSetting.getValue()&&this.fpsFastSetting.getValue());
this.registerEvent("worldLoad",this.worldLoad);


this.petLevels={};
this.petText="&6Pet&7> &fLoading...";
this.petElement.setText(this.petText);
this.registerChat("&cAutopet &eequipped your ${pet}&e! &a&lVIEW RULE&r",(pet)=>{
this.petElement.setText("&6Pet&7> "+pet);
this.petText="&6Pet&7> "+pet;

this.lastSwappedPet=Date.now();
});
this.registerChat("&r&aYou summoned your &r${pet}&r&a!&r",(pet)=>{
this.petElement.setText("&6Pet&7> &7[Lvl "+(this.petLevels[pet.replace("&","\xA7")]||"??")+"] "+pet);
this.petText="&6Pet&7> &7[Lvl "+(this.petLevels[pet.replace("&","\xA7")]||"??")+"] "+pet;

this.lastSwappedPet=Date.now();
});
this.registerChat("&r&aYou despawned your &r${*}&r&a!&r",()=>{
this.petElement.setText("&6Pet&7> &cNone");
this.petText="&6Pet&7> &cNone";

this.lastSwappedPet=Date.now();
});
this.registerChat("&r&aYour &r${pet} &r&alevelled up to level &r&9${level}&r&a!&r",(pet,level)=>{
if(ChatLib.removeFormatting(this.petText.split("] ")[1].trim())===ChatLib.removeFormatting(pet.trim())){
this.petElement.setText("&6Pet&7> &7[Lvl "+(level||"??")+"] "+pet);
this.petText="&6Pet&7> &7[Lvl "+(level||"??")+"] "+pet;
this.lastSwappedPet=Date.now();
}
});

this.registerSoopy("apiLoad",this.apiLoad);
if(this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock){
this.apiLoad(this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock,"skyblock",true,true);

this.lastSwappedPet=Date.now();
}
if(this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock_raw){
this.apiLoad(this.FeatureManager.features["dataLoader"].class.lastApiData.skyblock_raw,"skyblock",false,true);
}

this.registerStep(false,5,()=>{
if(!this.showSpotifyPlaying.getValue())return;

new Thread(()=>{
this.updateSpotify();
}).start();
});

this.registerActionBar("${m}",this.actionbarMessage);

this.packetMoves=0;
this.secondPackets=0;
this.tps=-2;
this.lastTps=[];
this.registerEvent("tick",this.tick);
this.registerStep(false,1,this.step_1second);
}

step_1second(){
if(World.getTime()/20/60/20>30&&this.showLobbyDayOnlyUnder30.getValue()){
this.lobbyDayElement.setText("");
}else{
if(World.getTime()!==0)this.lobbyDayElement.setText("&6Day&7> &f"+(World.getTime()/20/60/20).toFixed(2));
}

this.ppsCounterElement.setText("&6Packets&7> &f"+numberWithCommas(this.packetsSent)+"&7-&f"+numberWithCommas(this.packetsRecieved));

this.packetsSent=0;
this.packetsRecieved=0;

if(!this.lagEnabled.getValue()){
if(this.packetReceived){
this.packetReceived.unregister();
this.packetReceived=undefined;
}
return;
}
if(!this.packetReceived)this.packetReceived=register("packetReceived",()=>{
this.packetMoves++;
});
this.lastTps.push(this.secondPackets);
if(this.lastTps.length>10)this.lastTps.shift();
if(this.tps===-2){
this.tps=-1;
this.lastTps=[];
}
this.tps=this.lastTps.reduce((a,b)=>a+b,0)/this.lastTps.length;
this.secondPackets=0;

if(this.lastTps.length>1){
this.lagElement.setText("&6Tps&7> &f"+Math.min(20,this.tps).toFixed(1));
}else{
this.lagElement.setText("&6Tps&7> &fLOADING");
}
}

tick(){
if(this.fpsFastSetting.getValue()){
if(this.fpsLowSetting.getValue()){
this.fpsElement.setText("&6Fps&7> &f"+Math.round(this.fps.get())+"&7/"+Math.round(this.lowFps.get()));
}else{
this.fpsElement.setText("&6Fps&7> &f"+Math.round(this.fps.get()));
}
}

if(this.locationEnabledSetting.getValue()){

if(!this.locationOnlyDungSetting.getValue()||this.FeatureManager.features["dataLoader"].class.isInDungeon){
let locData=[];
locData.push(Player.getX());
if(this.locationYEnabledSetting.getValue())locData.push(Player.getY());
locData.push(Player.getZ());

locData=locData.map((a)=>a.toFixed(parseInt(this.locationDecimals.getValue())));

let locString=locData.join("&7 | &f");

this.locationElement.setText("&6Loc&7> &f"+locString);
}else{
this.locationElement.setText("");
}
}

if(!this.lagEnabled.getValue())return;
if(this.packetMoves>0){
this.secondPackets++;
this.packetMoves=0;
}
}

onDisable(){
this.fpsEnabledSetting.delete();
this.fpsFastSetting.delete();
this.cpsEnabledSetting.delete();

this.hudStat.forEach((h)=>h.textElement.delete());
this.hudElements.forEach((h)=>h.delete());

this.initVariables();

if(this.packetReceived)this.packetReceived.unregister();
}

renderHud(){
if(this.showSpotifyPlaying.getValue()&&Date.now()-this.spotifyElement.tempDisableTime>100){
let scale=this.spotifyElement.locationSetting.scale;
let spotifyWidth1=this.spotifyElement.getWidth()*scale;
this.spotifyElement2.locationSetting.x=this.spotifyElement.locationSetting.x+spotifyWidth1;
this.spotifyElement2.locationSetting.y=this.spotifyElement.locationSetting.y;
this.spotifyElement2.locationSetting.scale=scale;
this.spotifyElement2.locationSetting.shadowType=this.spotifyElement.locationSetting.shadowType;

let spotifyWidth2=this.spotifyElement2.getWidth()*scale;
if(spotifyWidth2>150*scale){
let w2=spotifyWidth2/scale-150;
let offX=Date.now()/50%(w2*2+100);
offX=Math.max(0,offX-50);
if(offX>w2+50){
offX=w2-(offX-w2-50);
}else if(offX>w2){
offX=w2;
}
this.spotifyElement2.locationSetting.x=this.spotifyElement.locationSetting.x+spotifyWidth1-offX*scale;

renderLibs.scizzorFast(this.spotifyElement.locationSetting.x+spotifyWidth1,this.spotifyElement2.locationSetting.y,150*scale,this.spotifyElement2.getHeight()*scale);
this.spotifyElement2.render();
renderLibs.stopScizzor();
}else{
this.spotifyElement2.render();
}
}

if(this.witherImpactCooldownSetting.getValue()&&Date.now()-this.lastWitherImpact<10000){
Renderer.drawString(Math.max(0,Math.ceil((5000-(Date.now()-this.lastWitherImpact))/1000))+"s",Renderer.screen.getWidth()/2-Renderer.getStringWidth(Math.max(0,Math.ceil((5000-(Date.now()-this.lastWitherImpact))/1000))+"s")/2,Renderer.screen.getHeight()/2-15);
}
}

renderWorld(){
this.framesSince++;

let instant=this.Instant.now();
let time=instant.getEpochSecond()+instant.getNano()/1000000000;

let thisframeTime=time-this.lastFrame;


if(thisframeTime>this.slowestFrameTime){
this.slowestFrameTime=thisframeTime;
}

this.lastFrame=time;
}

actionbarMessage(m){
if(ChatLib.removeFormatting(m).includes("(Wither Impact)")){
if(Date.now()-this.aup<750){
this.lastWitherImpact=Date.now();
this.aup=0;
}else{
this.impactTest=Date.now();
}
}
}

step(){
if(!Player.getPlayer())return;
let fps=0;

if(this.fpsEnabledSetting.getValue()&&this.fpsFastSetting.getValue()){


fps=this.framesSince/(this.lastFrame-this.lastTickTime);
if(this.lastFrame===this.lastTickTime)fps=0;
this.lastTickTime=this.lastFrame;
this.framesSince=0;

this.lastFrameRates.push(fps);
this.lastFrameRates.shift();

if(this.slowestFrameTime>0){
this.lastFrameRatesS.push(1/this.slowestFrameTime);
}else{
this.lastFrameRatesS.push(0);
}
this.lastFrameRatesS.shift();
this.slowestFrameTime=0;

fps=this.lastFrameRates.reduce((a,b)=>a+b,0)/this.lastFrameRates.length;
this.fps.set(fps,200);
if(this.fpsLowSetting.getValue())this.lowFps.set(this.lastFrameRatesS.reduce((a,b)=>a+b,0)/this.lastFrameRatesS.length,200);
}else{
fps=Client.getFPS();
this.fpsElement.setText("&6Fps&7> &f"+fps);
}

let cpsText=CPS.getLeftClicksAverage();

if(this.cpsIncludeRight.getValue()){
if(this.cpsSeperate.getValue()){
cpsText+="&7 | &f"+CPS.getRightClicksAverage();
}else{
cpsText+=CPS.getRightClicksAverage();
}
}
this.cpsElement.setText("&6Cps&7> &f"+cpsText);


if(this.scanGuiForPet.getValue()&&Player&&Player.getContainer()&&Player.getContainer().getName().includes(") Pets")){
let inv=Player.getContainer().getItems();
for(let i=0;i<inv.length;i++){
if(inv[i]!=null&&inv[i].getName().includes("[Lvl ")){
let level=inv[i].getName().split(" ")[1].replace("]","");
if(!this.petLevels[inv[i].getName().split("] ")[1]]||this.petLevels[inv[i].getName().split("] ")[1]]<level)this.petLevels[inv[i].getName().split("] ")[1]]=level;

if(Date.now()-this.lastSwappedPet>1000){
getLore(inv[i]).forEach((line)=>{
if(line.includes("Click to despawn!")){
this.petElement.setText("&6Pet&7> &7"+inv[i].getName().split("(")[0]);
this.petText="&6Pet&7> &7"+inv[i].getName().split("(")[0];
}
});
}
}
}
}

this.dragonDamageElement.setText("");

if(this.showDragonDamages.getValue()){

let playerDamage=-1;
let dragonHealth=-1;

Scoreboard.getLines().forEach((line)=>{
if(ChatLib.removeFormatting(line).startsWith("Your Damage: ")){
playerDamage=parseInt(ChatLib.removeFormatting(line).replace("Your Damage: ","").replace(/[^0-9\.]/g,""));
}
if(ChatLib.removeFormatting(line).startsWith("Dragon HP: ")){
dragonHealth=parseInt(ChatLib.removeFormatting(line).replace("Dragon HP: ","").replace(/[^0-9\.]/g,""));
}
});

if(playerDamage>-1){

let damages=[[Player.getName(),playerDamage]];
let dragonType="";

let lbNum=0;

TabList.getNames().forEach((n)=>{
l=ChatLib.removeFormatting(n);

if(lbNum>0){
lbNum--;



let name=l.split(":")[0].trim();

if(name===Player.getName())return;

let damage=l.split(" ").pop();

let actualDamage=parseFloat(damage);

if(damage.includes("k"))actualDamage*=1000;
if(damage.includes("M"))actualDamage*=1000000;

damages.push([name,actualDamage]);
}
if(l.startsWith("Dragon Fight: (")){
dragonType=l.split("(")[1].split(")")[0];

lbNum=3;
}
});

let text=`&6${dragonType} Dragon &7(&f${addNotation("oneLetters",dragonHealth,"&7")}&7 HP)`;

damages.sort((a,b)=>b[1]-a[1]).forEach((d)=>{
text+=`\n&7- &f${d[0]}&7: &f${addNotation("oneLetters",d[1],"&7")}`;
});

this.dragonDamageElement.setText(text);
}

}

if(this.showThunderingTimer.getValue()){
let time=rainTimer();

let text="&6Thunder&7> &7";
if(time.isThundering){
text+="&aNOW &7(&f"+formatTime(time.thunderstorm)+"&7)";
}else{
text+="in &f"+formatTime(time.thunderstorm);
}

if(this.showRain.getValue()){
text+="\n&6Rain&7> &7";
if(time.isRaining){
text+="&aNOW &7(&f"+formatTime(time.rain)+"&7)";
}else{
text+="in &f"+formatTime(time.rain);
}
}

this.thunderTimerElement.setText(text);
}

if(Player.getPlayer()["func_110139_bj"]()>this.lastAbsorbtion){
if(Date.now()-this.impactTest<750){
this.lastWitherImpact=Date.now();
this.impactTest=0;
}else{
this.aup=Date.now();
}
}
this.lastAbsorbtion=Player.getPlayer()["func_110139_bj"]();
}

step_5second(){
this.updateHudThingos();

if(!this.soulflowEnabledSetting.getValue())return;
if(!Player.getPlayer())return;
if(!Player.getInventory())return;

if(!this.FeatureManager.features["dataLoader"].class.isInSkyblock){
this.soulflowElement.setText("");
this.petElement.setText("");
return;
}else{
this.petElement.setText(this.petText);
}

if(!this.apiSoulflow){
this.soulflowElement.setText("");
return;
}

this.soulflowElement.setText("&6Soulflow&7> &f"+this.numberUtils.numberWithCommas(this.lastStatData.soulflow));
}

updatePotsTime(){
if(!this.showPotsHud.getValue())return;
if(!this.FeatureManager.features["dataLoader"].class.isInSkyblock||this.FeatureManager.features["dataLoader"].class.isInDungeon){
this.potsHudElement.setText("");
return;
}

let text="";

let godPotTime=-1;
if(this.potsExpireAt["water_breathing"]?.level===6&&
this.potsExpireAt["resistance"]?.level===8&&
basiclyEqual(this.potsExpireAt["water_breathing"]?.time,this.potsExpireAt["resistance"]?.time,10000)){
godPotTime=this.potsExpireAt["water_breathing"].time;
}

if(godPotTime>0&&godPotTime>Date.now()){
let timeLeft="";
if(godPotTime-Date.now()>60000*60){
timeLeft=timeNumber2(godPotTime-Date.now());
}else{
timeLeft=timeNumber(godPotTime-Date.now());
}
text+=`&6God potion&7>&f ${timeLeft}\n`;

if(this.potsOutAlert.getValue()&&godPotTime-Date.now()<60000&&Date.now()-(this.lastPotAlerts["godpot"]||0)>2*60000){
this.lastPotAlerts["godpot"]=Date.now();
Client.showTitle("&cPotion About to run out","Your &6God potion&f is about to run out!",20,60,20);
ChatLib.chat(this.FeatureManager.messagePrefix+"Your God potion is about to run out!");
}
}

Object.keys(this.potsExpireAt).forEach((k)=>{
let potData=this.potsExpireAt[k];
if(potData.infinite)return;
if(basiclyEqual(potData.time,godPotTime,10000))return;
if(potData.time<Date.now())return;

if(k==="haste"&&potData.level===1)return;

let potName=firstLetterCapital(k.replace(/_/g," "));

if(this.potsOutAlert.getValue()&&potData.time-Date.now()<60000&&Date.now()-(this.lastPotAlerts[k]||0)>2*60000){
this.lastPotAlerts[k]=Date.now();
Client.showTitle("&cPotion About to run out","Your &6"+potName+"&f is about to run out!",20,60,20);
ChatLib.chat(this.FeatureManager.messagePrefix+"Your "+potName+" is about to run out!");
}

let timeLeft="";
if(potData.time-Date.now()>60000*60){
timeLeft=timeNumber2(potData.time-Date.now());
}else{
timeLeft=timeNumber(potData.time-Date.now());
}

text+=`&6${potName} ${potData.level}&7> &f${timeLeft}\n`;
});
this.potsHudElement.setText(text);
}

updatePotsData(data,lastSave){
this.potsExpireAt={};
let now=Date.now();
if(Date.now()-lastSave<5*60000)now=lastSave;
data.active_effects.forEach((e)=>{
this.potsExpireAt[e.effect]={
level:e.level,
time:now+e.ticks_remaining*50,
infinite:e.infinite};

});
}

statApiLoadThingo(data){
let lastSave=0;
data.profiles.forEach((p)=>{
if(!this.lastStatData||p.selected){
this.lastStatData=p.members[Player.getUUID().toString().replace(/-/g,"")];
lastSave=p.last_save;
}
});

if(this.lastStatData){
this.updatePotsData(this.lastStatData,lastSave);
if(this.lastStatData.soulflow)this.apiSoulflow=true;

if(this.apiSoulflow)this.soulflowElement.setText("&6Soulflow&7> &f"+this.numberUtils.numberWithCommas(this.lastStatData.soulflow));
}

if(this.showLevelUpMessage.getValue()){
Object.keys(this.skillLevelCaps).forEach((skill)=>{
let skillData=getLevelByXp(this.lastStatData[skill],0,this.extendLevelCap.getValue()?Infinity:this.skillLevelCaps[skill]);
if(this.lastSkillLevel[skill]===skillData.level-1&&skillData.level>(this.skillLevelCaps[skill]===50?50:60)){
ChatLib.chat(`&r&3&l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬&r`);
ChatLib.chat(`  &r&b&lSKILL LEVEL UP &3${firstLetterCapital(skill.split("_").pop())} &8${skillData.level-1}➜&3${skillData.level}&r`);
ChatLib.chat(`&r  &r&a&lREWARDS&r\n&r  &r&6&lSoopy's Respect\n&r&3&l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬&r\n`);
}
this.lastSkillLevel[skill]=skillData.level;
});
}

this.updateHudThingos();
}

updateSpotify(){
if(!this.showSpotifyPlaying.getValue())return;

let currentSong="&cNot open";

if(this.spotifyProcessId!==-1){
let pid=this.spotifyProcessId;

let process=new ProcessBuilder("tasklist.exe","/FO","csv","/V","/FI","\"PID eq "+pid+"\"").start();
let sc=new Scanner(process.getInputStream());
if(sc.hasNextLine())sc.nextLine();
while(sc.hasNextLine()){
let line=sc.nextLine();
let parts=line.replace("\"","").split("\",\"");
let song=parts[parts.length-1].substr(0,parts[parts.length-1].length-1);
if(song==="N/A")continue;

if(song==="Spotify Free"||song==="Spotify Premium"||song==="AngleHiddenWindow"){
currentSong="&cPaused";
}else{
if(song==="Spotify")song="Advertisement";
currentSong="&a"+song.replace(/&/g,"&\u2B4D").replace(" - "," &7-&b ");
}

}
process.waitFor();

this.spotifyElement2.setText(currentSong.normalize("NFD").replace(/[\u0300-\u036f]/g,""));
}

if(currentSong!=="&cNot open")return;

this.spotifyProcessId=-1;
let spotifyProcesses=[];
let process=new ProcessBuilder("tasklist.exe","/fo","csv","/nh").start();
let sc=new Scanner(process.getInputStream());
if(sc.hasNextLine())sc.nextLine();
while(sc.hasNextLine()){
let line=sc.nextLine();
let parts=line.replace("\"","").split("\",\"");
let unq=parts[0];
let pid=parts[1];
if(unq==="Spotify.exe"){
spotifyProcesses.push(pid);

}
}
process.waitFor();

while(spotifyProcesses.length>0){
let pid=spotifyProcesses.pop();

let process=new ProcessBuilder("tasklist.exe","/FO","csv","/V","/FI","\"PID eq "+pid+"\"").start();
let sc=new Scanner(process.getInputStream());
if(sc.hasNextLine())sc.nextLine();
while(sc.hasNextLine()){
let line=sc.nextLine();
let parts=line.replace("\"","").split("\",\"");
let song=parts[parts.length-1].substr(0,parts[parts.length-1].length-1);
if(song==="N/A")continue;

this.spotifyProcessId=pid;

if(song==="Spotify Free"||song==="Spotify Premium"||song==="AngleHiddenWindow"){
currentSong="&cPaused";
}else{
if(song==="Spotify")song="Advertisement";
currentSong="&a"+song.replace(/&/g,"&\u2B4D").replace(" - "," &7-&b ");
}

}
process.waitFor();
}

this.spotifyElement2.setText(currentSong.normalize("NFD").replace(/[\u0300-\u036f]/g,""));
}

updateHudThingos(){
let insb=!!this.FeatureManager.features["dataLoader"].class?.isInSkyblock;

this.hudStat.forEach((stat)=>{
if(stat.enabled.getValue()){
this.updateHudThing(stat,insb);
}else{
stat.textElement.setText("");
}
});
}

updateHudThing(thing,insb){
if(!this.lastStatData)return;

if(!insb&&thing.onlySb.getValue()){
thing.textElement.setText("");
return;
}

let type=thing.type.getValue();

let string="Unknown stat";
if(type==="totaldeaths"){
string="&6Deaths&7> &f"+this.numberUtils.numberWithCommas(this.lastStatData.death_count);
}
if(type==="cata"){
let cataData=getLevelByXp(this.lastStatData.dungeons.dungeon_types.catacombs.experience,2,Infinity);
string="&6Cata&7> &f"+(~~((cataData.level+cataData.progress)*100)/100).toFixed(2)+" &7("+this.numberUtils.numberWithCommas(cataData.xpCurrent)+(cataData.level===50?"":"/"+this.numberUtils.numberWithCommas(cataData.xpForNext))+")";
}
if(type==="mythril_powder"){
string="&6Mithril Powder&7> &f"+numberWithCommas(this.lastStatData.mining_core.powder_mithril_total);
}
if(type==="gemstone_powder"){
string="&6Gemstone Powder&7> &f"+numberWithCommas(this.lastStatData.mining_core.powder_gemstone_total);
}

Object.keys(this.skillLevelCaps).forEach((skill)=>{
if(type===skill){
let skillData=getLevelByXp(this.lastStatData[skill],0,this.extendLevelCap.getValue()?Infinity:this.skillLevelCaps[skill]);
this.lastSkillLevel[skill]=skillData.level;
string="&6"+firstLetterCapital(skill.split("_").pop())+"&7> &f"+(skillData.level+skillData.progress).toFixed(2)+" &7("+this.numberUtils.numberWithCommas(skillData.xpCurrent)+(skillData.level===this.skillLevelCaps[skill]?"":"/"+this.numberUtils.numberWithCommas(skillData.xpForNext))+")";
}
});

if(type==="completions_enterance"){
string="&6E Comps&7> &f"+this.numberUtils.numberWithCommas(this.lastStatData.dungeons?.dungeon_types?.catacombs?.tier_completions?.[0]||0);
}
if(type.startsWith("completions_floor_")){
let floor=parseInt(type.split("_").pop());
string="&6F"+floor+" Comps&7> &f"+this.numberUtils.numberWithCommas(this.lastStatData.dungeons?.dungeon_types?.catacombs?.tier_completions?.[floor]||0);
}
if(type.startsWith("completions_master_")){
let floor=parseInt(type.split("_").pop());
string="&6M"+floor+" Comps&7> &f"+this.numberUtils.numberWithCommas(this.lastStatData.dungeons?.dungeon_types?.master_catacombs?.tier_completions?.[floor]||0);
}
if(type.startsWith("completions_dungeon_")){
let floor=parseInt(type.split("_").pop());
string="&6Dungeon "+floor+" Comps&7> &f"+this.numberUtils.numberWithCommas((this.lastStatData.dungeons?.dungeon_types?.catacombs?.tier_completions?.[floor]||0)+(this.lastStatData.dungeons?.dungeon_types?.master_catacombs?.tier_completions?.[floor]||0));
}

thing.textElement.setText(string);
}

apiLoad(data,dataType,isSoopyServer,isLatest){
if(dataType==="skyblock"&&!isSoopyServer){
this.statApiLoadThingo(data);
}
if(!isSoopyServer||!isLatest)return;
if(dataType!=="skyblock")return;

let pet=data.data.profiles[data.data.stats.currentProfileId].members[Player.getUUID().replace(/-/g,"")].selectedPet;

if(!pet){
this.petElement.setText("&6Pet&7> &cNone");
this.petText="&6Pet&7> &cNone";
return;
}

let petTierColor={
"COMMON":"&f",
"UNCOMMON":"&a",
"RARE":"&9",
"EPIC":"&5",
"LEGENDARY":"&6",
"MYTHIC":"&d"};


this.petText="&6Pet&7> &7[Lvl "+(pet.level.level||"??")+"] "+petTierColor[pet.tier]+pet.name;
this.petElement.setText(this.petText);
}

worldLoad(){
this.lastUpdatedStatData=0;
this.packetMoves=0;
this.secondPackets=0;
this.tps=-2;
this.lastTps=[];
this.lagElement.setText("&6Tps&7> &fLOADING");
}}


module.exports={
class:new Hud};



const rainingTime=1000*1000;
const rainInterval=4850*1000;
const thunderstormInterval=rainInterval*4;
const PrevThunderstormTime=1668551956000;

function rainTimer(){
let timeSinceThunderStart=(Date.now()-PrevThunderstormTime)%thunderstormInterval;

let timeTillThunder=thunderstormInterval-timeSinceThunderStart;

let nextRain=timeTillThunder%rainInterval;

let isRaining=nextRain<rainingTime;
let isThundering=timeTillThunder<rainingTime;

return{rain:isRaining?nextRain:nextRain-rainingTime,thunderstorm:isThundering?timeTillThunder:timeTillThunder-rainingTime,isRaining,isThundering};
}