import * as mc from "@minecraft/server";

export function clearItem(block, slot, count) {
   let selectedSlot = block.getItem(slot);
   if (selectedSlot.amount > count) {
      selectedSlot.amount = selectedSlot.amount - count;
      block.setItem(slot, selectedSlot);
   } else {
      let air = new mc.ItemStack("minecraft:air");
      block.setItem(slot, air);
   }
}
export function calcularDistancia(coord1, coord2) {
   const distancia = Math.sqrt(
      Math.pow(coord2[0] - coord1[0], 2) +
      Math.pow(coord2[1] - coord1[1], 2) +
      Math.pow(coord2[2] - coord1[2], 2)
   );
   return distancia;
}
export function calculateMovement(start, end) {
    return {
        x: end.x - start.x,
        y: end.y - start.y,
        z: end.z - start.z
    }
}
export function clearMainhand(player, count) {
   if (player.getGameMode() == 'survival'){
      let selectedSlot = player.getComponent("equippable").getEquipment("Mainhand")
      if (selectedSlot.amount > count) {
         selectedSlot.amount = selectedSlot.amount - count;
         player.getComponent("equippable").setEquipment("Mainhand", selectedSlot);
      } else {
         let air = new mc.ItemStack("minecraft:air");
         player.getComponent("equippable").setEquipment("Mainhand", air);
      }
   } else {
      const selectedSlot = player.getComponent("equippable").getEquipment("Mainhand")
      selectedSlot.clearDynamicProperties()
      player.getComponent("equippable").setEquipment("Mainhand", selectedSlot);
   }
}
function clearOffhand(player, count) {
   let selectedSlot = player.getComponent("equippable").getEquipment("Offhand")
   if (selectedSlot.amount > count) {
      selectedSlot.amount = selectedSlot.amount - count;
      player.getComponent("equippable").setEquipment("Offhand", selectedSlot);
   } else {
      let air = new mc.ItemStack("minecraft:air");
      player.getComponent("equippable").setEquipment("Offhand", air);
   }
}
export function setPermutation(block, stateAdd, stateValue) {
   const result = block.permutation.getAllStates();
   result[stateAdd] = stateValue;
   block.setPermutation(mc.BlockPermutation.resolve(block?.typeId, result));
}
export function isBlockId(block, id){
    let cm = block?.dimension?.runCommand(`testforblock ${block?.location.x} ${block?.location.y} ${block?.location.z} ${id}`).successCount
    if (cm > 0) return true; else return false
}

export function applyDurability(item, amount){
   if (item && amount){
      const durability = item.getComponent('minecraft:durability')
      const currentValue = durability.maxDurability - durability.damage
      if (durability.damage+amount >= durability.maxDurability){
         return new mc.ItemStack('minecraft:air')
      } else if (durability.damage+amount < durability.maxDurability){
         item.getComponent('minecraft:durability').damage = item.getComponent('minecraft:durability').damage+amount
         return item
      }
   }
}

mc.system.afterEvents.scriptEventReceive.subscribe((data) => {
   if (data.id == 'rc_fb:despawn'){data.sourceEntity.remove()}
})

export function isJSONParsable(str) {
   try {
       JSON.parse(str);
       return true;
   } catch (e) {
       return false;
   }
}

export function removeStringFromArray(arr, str) {
   return arr.filter(item => item !== str);
}

export function generateCircleVectors(n, r, center) {
   let vectors = [];
   let angleIncrement = (2 * Math.PI) / n;

   for (let i = 0; i < n; i++) {
       let angle = i * angleIncrement;
       let x = center.x + r * Math.cos(angle);
       let y = center.y; // Presumindo que o círculo está no plano XZ
       let z = center.z + r * Math.sin(angle);
       vectors.push({ x: x, y: y, z: z });
   }

   return vectors;
}
export function calculateRelativeVector(vector1, vector2) {
    return {
        x: vector2.x - vector1.x,
        y: vector2.y - vector1.y,
        z: vector2.z - vector1.z
    };
}



export function blockFaceToDirection(face){
   if (face == 'Up') return 'above'; else
   if (face == 'Down') return 'below'; else
   if (face?.includes('up')) return 'above'; else
   if (face?.includes('down')) return 'below'; else
   if (face == 'North') return 'north'; else
   if (face == 'South') return 'south'; else
   if (face == 'West') return 'west'; else
   if (face == 'East') return 'east'; else return (face)
}
export function invertFace(face){
   if (face == 'up') return 'down'
   if (face == 'down') return 'up'
   if (face == 'above') return 'below'
   if (face == 'below') return 'above'
   if (face == 'north') return 'south'
   if (face == 'south') return 'north'
   if (face == 'west') return 'east'
   if (face == 'east') return 'west'
       
}
export function includesAnyIndex(str, arr) {
   return arr.findIndex(subStr => str.includes(subStr));
 }
export function generateRandomID(length) {
   let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
   let randomID = '';
   for (let i = 0; i < length; i++) {
       randomID += characters.charAt(Math.floor(Math.random() * characters.length));
   }
   return randomID;
}

export const transformKey = str => 
   str.split(':')[1].replace(/_/g, ' ').toLowerCase().replace(/\b\w/g, c => c.toUpperCase())

const normalize = str => str.toLowerCase().replace(/[_ :]/g, '')
const filterProperties = (obj, search) => Object.fromEntries(
   Object.entries(obj).filter(([k]) => normalize(k).includes(normalize(search)))
)
export function numToDirection(number){
    if (number == 0) return "up"
    if (number == 1) return "down"
    if (number == 2) return "north"
    if (number == 3) return "south"
    if (number == 4) return "west"
    if (number == 5) return "east"
}
export function invertUpDown(face){
    if (face == 'below') return 'above'; else
    if (face == 'above') return 'below'; else
    if (face == 'up') return 'down'; else
    if (face == 'down') return 'up'; else return face
}

export function includesAny(str, arr) {
   return arr.some(subStr => str.includes(subStr));
 }
export function createDashedLine(viewDirection, playerPosition, numSegments, segmentLength, segmentStart) {
   const directionMagnitude = Math.sqrt(viewDirection.x * viewDirection.x + viewDirection.y * viewDirection.y + viewDirection.z * viewDirection.z)
   viewDirection.x /= directionMagnitude
   viewDirection.y /= directionMagnitude
   viewDirection.z /= directionMagnitude
   let points = []
   for (let i = segmentStart; i < numSegments; i++) {
       let distance = i * segmentLength
       let point = {
           x: playerPosition.x + viewDirection.x * distance,
           y: playerPosition.y + viewDirection.y * distance,
           z: playerPosition.z + viewDirection.z * distance
       }
       points.push(point)
   }
   return points
}
export function addVectors(v1, v2) {
   return { x: v1.x + v2.x, y: v1.y + v2.y, z: v1.z + v2.z };
}
export function divideVectorBy(vector, times) {
   return { x: vector.x / times, y: vector.y / times, z: vector.z / times };
}
export function rotateVector(vector, times) {
   const rotations = times % 4
   let { x, y, z } = vector
   for (let i = 0; i < rotations; i++) {
       [x, z] = [z, -x]
   }
   return { x, y, z };
}
export function relativeToAbsolute(base, relative) {
   return {
       x: base.x + relative.x,
       y: base.y + relative.y,
       z: base.z + relative.z
   };
}

export function getDirection(vectorA, vectorB) {
   const direction = {
       x: vectorB.x - vectorA.x,
       y: vectorB.y - vectorA.y,
       z: vectorB.z - vectorA.z
   };

   // Normaliza a direção
   const magnitude = Math.sqrt(direction.x ** 2 + direction.y ** 2 + direction.z ** 2);
   
   return {
       x: direction.x / magnitude,
       y: direction.y / magnitude,
       z: direction.z / magnitude
   };
}
export function blockFloorCenter(block){
    return {x:block.center().x, y:block.location.y, z:block.center().z}
}
export function operationWithVectorPLUS(vector, x, y, z){
    let newVector = {x:vector.x+x, y:vector.y-0.4, z:vector.z+z}
    if (newVector) return newVector
}
export function operationWithVectorMINUS(vector, x, y, z){
    let newVector = {x:vector.x-x, y:vector.y-0.4, z:vector.z-z}
    if (newVector) return newVector
}
export function trueFace(block, face){
   const state = block?.permutation?.getState("minecraft:cardinal_direction")
   if (state){
       if (state == 'north'){
           if (face == 'north') return 'north'; else
           if (face == 'south') return 'south'; else
           if (face == 'west') return 'west'; else
           if (face == 'east') return 'east'; else return face
       } else 
       if (state == 'west'){
           if (face == 'north') return 'east'; else
           if (face == 'south') return 'west'; else
           if (face == 'west') return 'north'; else
           if (face == 'east') return 'south'; else return face
       } else 
       if (state == 'south'){
           if (face == 'north') return 'south'; else
           if (face == 'south') return 'north'; else
           if (face == 'west') return 'east'; else
           if (face == 'east') return 'west'; else return face
       } else 
       if (state == 'east'){
           if (face == 'north') return 'west'; else
           if (face == 'south') return 'east'; else
           if (face == 'west') return 'south'; else
           if (face == 'east') return 'north'; else return face
       }
   } else return face
}

export function convergeDirection(direction){
   if (direction == 'north') return 'north'; else
   if (direction == 'south') return 'north'; else
   if (direction == 'west') return 'west'; else
   if (direction == 'east') return 'west'; else
   if (direction == 'up') return 'up'; else
   if (direction == 'down') return 'up'; else
   if (direction == 'above') return 'above'; else
   if (direction == 'below') return 'above'; else direction

}
export function itemIsBlock(block, item) {
    if (
        item?.typeId == 'minecraft:bedrock'
    )
    {
        return true
    } else
   if (
        item?.typeId?.includes("kelp") && !item?.typeId == 'minecraft:dried_kelp_block' || 
        item?.typeId?.includes("amethyst_bud") || 
        item?.typeId?.includes("amethyst_cluster") || 
        item?.typeId?.includes("wheat") || 
        item?.typeId?.includes("beetroot") || 
        item?.typeId?.includes("coral") || 
        item?.typeId?.includes("vine") ||   
        item?.typeId?.includes("glowstone_dust") ||          
        item?.typeId?.includes("hopper") ||                  
        item?.typeId?.includes("chain") ||                   
        item?.typeId?.includes("dripstone") ||               
        item?.typeId == "minecraft:bamboo" ||                        
       item?.typeId?.includes("candle") ||                  
       item?.typeId?.includes("campfire") ||                
       item?.typeId?.includes("cauldron") ||                
       item?.typeId?.includes("armor_stand") ||             
       item?.typeId?.includes("sign") ||                    
       item?.typeId?.includes("item_frame") ||              
       item?.typeId?.includes("painting") ||                
       item?.typeId?.includes("mushroom") ||                
       item?.typeId?.includes("bell") ||                    
       item?.typeId?.includes("rail") ||                    
       item?.typeId?.includes("shovel") ||                  
       item?.typeId?.includes("torch") ||                   
       item?.typeId?.includes("amethyst_cluster") ||        
       item?.typeId?.includes("blud") ||        
       item?.typeId?.includes("door") ||                    
       item?.typeId?.includes("ladder") ||                  
       item?.typeId?.includes("iron_bars") ||               
       item?.typeId?.includes("bed") ||
       item?.typeId == "minecraft:bamboo" ||
       item?.typeId == "minecraft:lantern" ||
       item?.typeId == "minecraft:soul_lantern" ||
       item?.typeId == "minecraft:deadbush" ||
       item?.typeId == "minecraft:sniffer_egg" ||
       item?.typeId?.includes("sea_pickle") ||
       item?.typeId?.includes("brewing_stand") ||
       item?.typeId?.includes("frame") ||
       item?.typeId?.includes("tripwire_hook") ||
       item?.typeId?.includes("minecraft:lever") ||
       item?.typeId?.includes("amethyst") ||
       item?.typeId?.includes("poppy") ||
       item?.typeId?.includes("sapling")
   ){
       return false
   } else
   {
       try {
           if (block.dimension.runCommand(`setblock ${block.x} -64 ${block.z} ${item?.typeId}`).successCount > 0) {
               block.dimension.runCommand(`setblock ${block.x} -64 ${block.z} bedrock`)
               return true;
           } else {
               return false;
           }
       } catch (error) {
           return false;
       }
   }
}

export function placerItemIsBlock(block, item) {
    if ( item?.typeId == 'minecraft:bedrock' ) {
        return true
    } else
    try {
        if (block.dimension.runCommand(`setblock ${block.x} -64 ${block.z} ${item?.typeId}`).successCount > 0) {
            block.dimension.runCommand(`setblock ${block.x} -64 ${block.z} bedrock`)
            return true;
        } else {
            return false;
        }
    } catch (error) {
        return false;
    }
}

export function transferItem(containerA, containerB, i, amountRequested){
   const itemA = containerA?.getItem(i)
   if (itemA && itemA?.amount >= amountRequested){
       let hasSpace = false
       if (containerB.emptySlotsCount > 0) hasSpace = true; else
       for (let o = 0; o < containerB.size; o++){
           const containerItem = containerB.getItem(o)
           if (containerItem?.isStackableWith(playerItem) && containerItem.amount + amountRequested <= containerItem.maxAmount){
               hasSpace = true
           }
       }
       if (hasSpace){
           if (itemA.amount > amountRequested){
               itemA.amount -= amountRequested
               containerA.setItem(i, itemA)
               itemA.amount = amountRequested
               containerB.addItem(itemA)
               return true
           } else
           if (itemA.amount == amountRequested){
               containerA.setItem(i, )
               itemA.amount = amountRequested
               containerB.addItem(itemA)
               return true
           }
       }
   }
}
export function transferEntityItem(entityItem, containerB, amountRequested){
   const itemA = entityItem?.getComponent('minecraft:item')?.itemStack
   if (itemA && itemA?.amount >= amountRequested){
       let hasSpace = false
       if (containerB?.emptySlotsCount > 0) hasSpace = true; else
       for (let o = 0; o < containerB?.size; o++){
           const containerItem = containerB.getItem(o)
           if (containerItem?.isStackableWith(itemA) && containerItem.amount + amountRequested <= containerItem.maxAmount){
               hasSpace = true
           }
       }
       if (hasSpace){
           if (itemA.amount > amountRequested){
               const itemfudido = entityItem.dimension.spawnItem(new mc.ItemStack(itemA?.typeId, itemA.amount-amountRequested), entityItem.location)
               itemfudido.teleport(itemfudido.location)
               itemA.amount = amountRequested
               entityItem?.remove()
               containerB.addItem(itemA)
               return true
           } else
           if (itemA.amount == amountRequested){
               entityItem.remove()
               itemA.amount = amountRequested
               containerB.addItem(itemA)
               return true
           }
       }
   }
}




export function formatString(str) {
    return str
      .split(/_| /) // Divide a string em palavras, considerando "_" e espaços
      .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) // Capitaliza a inicial de cada palavra
      .join(' '); // Junta as palavras com espaços
  }









export function removeRedstonePower(origin, direction) {
    let visitedBlocks = [];
    let sources = [];
    let wires = [];
    let queue = [];

    for (const face of direction) {
        queue.push(origin[face]());
    }

    while (queue.length > 0) {
        const block = queue.shift();

        if (!visitedBlocks.includes(JSON.stringify(block.location))) {
            visitedBlocks.push(JSON.stringify(block.location));

            if (block?.typeId == 'minecraft:redstone_wire') {
                if (!wires.includes(JSON.stringify(block.location))) {
                    wires.push(JSON.stringify(block.location))
                }
                racoAPI.setPermutation(block, "redstone_signal", 0);
                //block.dimension.spawnParticle('minecraft:basic_smoke_particle', block?.center());
            }

            let faces = [];
            if (block?.typeId == 'minecraft:redstone_wire') {
                faces = redstoneConnecter(block, true);
            }

            for (const thisFace of faces) {
                let thisBlock;
                if (thisFace?.includes('().')) {
                    const split = thisFace.split('().');
                    thisBlock = block[split[0]]()[split[1]]();
                } else {
                    thisBlock = block[thisFace]();
                }

                if (sourceIds.includes(thisBlock.typeId) || thisBlock.typeId.includes('button') || thisBlock.typeId.includes('pressure_plate')){
                    sources.push(JSON.stringify(thisBlock.location))
                }

                if (block?.typeId == 'minecraft:redstone_wire' || isSolid(block)) {
                    queue.push(thisBlock);
                }
            }
        }
    }
    //console.warn(wires.length, sources.length)
    for (const thisLoc of sources){
        const thisBlock = origin.dimension.getBlock(JSON.parse(thisLoc))
        setRedstonePower(thisBlock, ['above', 'below', 'north', 'south', 'west', 'east'], 15)
    }
}

export function locToCommand(block){
    return `${block.x} ${block.y} ${block.z}`
}

export function isSolid(blockTested) {
    let block = blockTested.typeId
    const nonSolidBlocks = new Set([
        "dandelion", "poppy", "blue_orchid", "allium", "azure_bluet", "red_tulip", "orange_tulip", "white_tulip", "pink_tulip", "oxeye_daisy", "sunflower", "lilac",
        "rose_bush", "peony", "cornflower", "lily_of_the_valley", "tallgrass", "fern", "large_fern", "deadbush", "seagrass", "air", "waterlily", "vine", "ladder", "rail",
        "golden_rail", "activator_rail", "tripwire_hook", "beacon", "web", "snow_layer", "iron_bars", "chain", "scaffolding", "bamboo", "sea_pickle", "conduit",
        "lightning_rod", "sweet_berry_bush", "small_dripleaf_block", "big_dripleaf", "flower_pot", "amethyst_cluster", "budding_amethyst", "pointed_dripstone", 
        "glow_lichen",  "spore_blossom", "hanging_roots", "end_rod", "bell", "lantern", "soul_lantern", "chain", "soul_fire", "bubble_column", "redstone_wire", "rc_fb:vacuum_hopper"
    ]);
    if (block.includes('slab') || block.includes('glass') || block.includes('carpet') || block.includes('leaves') || block.includes('vines')
    || block.includes('coral') || block.includes('torch') || block.includes('mushroom') || block.includes('sign') || block.includes('banner')
    || block.includes('frame') || block.includes('portal') || block.includes('campfire') || nonSolidBlocks.has(block.replace('minecraft:', ''))) return false;
    else return true;
}