//This code is property of ID from VFS, DO NOT COPY OR STEAL! otherwiese you'll receive an copyright strike!

import {
    world,
    DynamicPropertiesDefinition,
    MinecraftEntityTypes,
    system,
    Location,
    Vector,
    MolangVariableMap
} from '@minecraft/server';

import {
    ActionFormData
} from '@minecraft/server-ui';


function getInv(target) {
    let container = target.getComponent('inventory')?.container;
    if (!container)
        return [];
    return new Array(container.size).fill(undefined).map((v, i) => container.getItem(i));
}


world.events.worldInitialize.subscribe((e) => {
  let def = new DynamicPropertiesDefinition();
  def.defineString("rpgRole", 25);
  e.propertyRegistry.registerEntityTypeDynamicProperties(def, MinecraftEntityTypes.player);
});

///first part///////////////////////////////////////

world.events.beforeDataDrivenEntityTriggerEvent.subscribe((event) => {
  const entity = event.entity;
  const eventId = event.id;
  if (entity.typeId !== 'minecraft:player') return
  const inventory = entity.getComponent('minecraft:inventory').container;
  const item = inventory.getItem(entity.selectedSlot);
  if (item.typeId.startsWith('sw:')) {
      const lores = item.getLore();
      if (eventId.endsWith('_fire')) {
        if ((world.scoreboard.getObjective("ammo").getScore(entity.scoreboard)) == 0) {
        try {
            const lores = item.getLore();
            lores[0] = `§rammo: ${world.scoreboard.getObjective("ammo").getScore(entity.scoreboard)}`;
            item.setLore(lores);
            player.getComponent("inventory").container.setItem(entity.selectedSlot, item);
            console.warn(lores)
          } catch (err) { console.error(err) }
          }
      };
      if (eventId.startsWith('equip')) {
            if (item && (item.getLore() == undefined || item.getLore().length == 0)) {
                if (item.typeId.startsWith('sw:')) {
                    if (item.typeId.endsWith('dc15s')) {
                        item.setLore(['§rammo: 100', 'Blaster Rifle']);
                    };
                    if (item.typeId.endsWith('e5')) {
                        item.setLore(['§rammo: 125', 'Blaster Rifle']);
                    };
                    if (item.typeId.endsWith('z6_rotary')) {
                        item.setLore(['§rammo: 999', 'Rotary Blaster']);
                    };
                    if (item.typeId.endsWith('dc15a')) {
                        item.setLore(['§rammo: 350', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dc15x')) {
                        item.setLore(['§rammo: 40', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dc17')) {
                        item.setLore(['§rammo: 75', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('dc17m')) {
                        item.setLore(['§rammo: 400', 'Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dh17')) {
                        item.setLore(['§rammo: 80', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('ec17')) {
                        item.setLore(['§rammo: 50', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('se14')) {
                        item.setLore(['§rammo: 65', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('e11')) {
                        item.setLore(['§rammo: 200', 'Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('e11d')) {
                        item.setLore(['§rammo: 250', 'Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dlt19')) {
                        item.setLore(['§rammo: 450', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dlt19d')) {
                        item.setLore(['§rammo: 65', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dlt19x')) {
                        item.setLore(['§rammo: 55', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('rt97c')) {
                        item.setLore(['§rammo: 420', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('btx42')) {
                        item.setLore(['§rammo: 999', 'Flamethrower'])
                    };
                    if (item.typeId.endsWith('rps6')) {
                        item.setLore(['§rammo: 1', 'Rocketlauncher'])
                    };
                    if (item.typeId.endsWith('a280')) {
                        item.setLore(['§rammo: 150', 'Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('westar35')) {
                        item.setLore(['§rammo: 77', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('dc17_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('dh17_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('ec17_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('se14_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('westar35_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    entity.getComponent("inventory").container.setItem(entity.selectedSlot, item);
                }
            };
                     entity.runCommandAsync(`scoreboard players set @s ammo ${item.getLore()[0].replace('§rammo: ', '')}`);
            };
            if (eventId.startsWith('empty_score')) {
              if (item.getLore()[1] == 'Blaster Pistol') {
                  let c = 0;
                  getInv(entity).filter(v => v?.typeId == 'sw:small_energycell').forEach(v => c += v.amount);
                   entity.runCommandAsync(`titleraw @s actionbar {"rawtext":[{"text":"§l§4Empty§r,\n§6magazines left: ${c}"}]}`);
                   entity.runCommandAsync(`scoreboard players set @s small_energycell ${c}`);
              };
              if (item.getLore()[1] == 'Dual Blaster Pistol') {
                  let c = 0;
                  getInv(entity).filter(v => v?.typeId == 'sw:small_energycell').forEach(v => c += v.amount);
                   entity.runCommandAsync(`titleraw @s actionbar {"rawtext":[{"text":"§l§4Empty§r,\n§6magazines left: ${c}/2"}]}`);
                   entity.runCommandAsync(`scoreboard players set @s small_energycell ${c}`);
              };
              if (item.getLore()[1] == 'Rotary Blaster') {
                  let c = 0;
                  getInv(entity).filter(v => v?.typeId == 'sw:large_energycell').forEach(v => c += v.amount);
                   entity.runCommandAsync(`titleraw @s actionbar {"rawtext":[{"text":"§l§4Empty§r,\n§6magazines left: ${c}/2"}]}`);
                   entity.runCommandAsync(`scoreboard players set @s large_energycell ${c}`);
              };
              if (item.getLore()[1] == 'Blaster Rifle') {
                  let c = 0;
                  getInv(entity).filter(v => v?.typeId == 'sw:energycell').forEach(v => c += v.amount);
                   entity.runCommandAsync(`titleraw @s actionbar {"rawtext":[{"text":"§l§4Empty§r,\n§6magazines left: ${c}"}]}`);
                   entity.runCommandAsync(`scoreboard players set @s energycell ${c}`);
              };
              if (item.getLore()[1] == 'Heavy Blaster Rifle') {
                  let c = 0;
                  getInv(entity).filter(v => v?.typeId == 'sw:large_energycell').forEach(v => c += v.amount);
                   entity.runCommandAsync(`titleraw @s actionbar {"rawtext":[{"text":"§l§4Empty§r,\n§6magazines left: ${c}"}]}`);
                   entity.runCommandAsync(`scoreboard players set @s large_energycell ${c}`);
              };
              if (item.getLore()[1] == 'Rocketlauncher') {
                  let c = 0;
                  getInv(entity).filter(v => v?.typeId == 'sw:rps6_rocket').forEach(v => c += v.amount);
                   entity.runCommandAsync(`titleraw @s actionbar {"rawtext":[{"text":"§l§4Empty§r,\n§6magazines left: ${c}"}]}`);
                   entity.runCommandAsync(`scoreboard players set @s rps6_rocket ${c}`);
              };
            };
            if (eventId.startsWith('reload_end')) {
            let lorenew = item.getLore();
            lorenew[0] = `§rammo: ${world.scoreboard.getObjective("ammo").getScore(entity.scoreboard)}`;
            item.setLore(lorenew);
            entity.getComponent("inventory").container.setItem(entity.selectedSlot, item);
            };
  }
});



let slot = new Map()

world.events.itemStartCharge.subscribe(event => {
 slot.set(event.source.id, event.source.selectedSlot)
})

world.events.itemStopCharge.subscribe(event => {
  let { source: player, itemStack: item } = event
        if (item.typeId.startsWith('sw:') && (item.getLore() != undefined || item.getLore().length != 0)) {
            const lores = item.getLore();
            lores[0] = `§rammo: ${world.scoreboard.getObjective("ammo").getScore(player.scoreboard)}`;
            item.setLore(lores);
            player.getComponent("inventory").container.setItem(slot.get(player.id) ?? player.selectedSlot, item);
            console.warn(lores)
        }
})



let lastSlotData = new Map()

async function checkSlot(){
    try{
    let players = world.getAllPlayers()

    players.forEach( async (player) => {
        let oldSlot = lastSlotData.get( player.id  )
        let nowSlot = player.selectedSlot
        
        if ( oldSlot != null && oldSlot != nowSlot  ) {
            const inventory = player.getComponent('minecraft:inventory').container;
            const item = inventory.getItem(player.selectedSlot);
            
            if (item.typeId.startsWith('sw:')) {
                const lores = item.getLore();
              if (item.getLore() == undefined || item.getLore().length == 0) {
                if (item.typeId.startsWith('sw:')) {
                    if (item.typeId.endsWith('dc15s')) {
                        item.setLore(['§rammo: 100', 'Blaster Rifle']);
                    };
                    if (item.typeId.endsWith('e5')) {
                        item.setLore(['§rammo: 125', 'Blaster Rifle']);
                    };
                    if (item.typeId.endsWith('z6_rotary')) {
                        item.setLore(['§rammo: 999', 'Rotary Blaster']);
                    };
                    if (item.typeId.endsWith('dc15a')) {
                        item.setLore(['§rammo: 350', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dc15x')) {
                        item.setLore(['§rammo: 40', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dc17')) {
                        item.setLore(['§rammo: 75', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('dc17m')) {
                        item.setLore(['§rammo: 400', 'Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dh17')) {
                        item.setLore(['§rammo: 80', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('ec17')) {
                        item.setLore(['§rammo: 50', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('se14')) {
                        item.setLore(['§rammo: 65', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('e11')) {
                        item.setLore(['§rammo: 200', 'Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('e11d')) {
                        item.setLore(['§rammo: 250', 'Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dlt19')) {
                        item.setLore(['§rammo: 450', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dlt19d')) {
                        item.setLore(['§rammo: 65', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('dlt19x')) {
                        item.setLore(['§rammo: 55', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('rt97c')) {
                        item.setLore(['§rammo: 420', 'Heavy Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('btx42')) {
                        item.setLore(['§rammo: 999', 'Flamethrower'])
                    };
                    if (item.typeId.endsWith('rps6')) {
                        item.setLore(['§rammo: 1', 'Rocketlauncher'])
                    };
                    if (item.typeId.endsWith('a280')) {
                        item.setLore(['§rammo: 150', 'Blaster Rifle'])
                    };
                    if (item.typeId.endsWith('westar35')) {
                        item.setLore(['§rammo: 77', 'Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('dc17_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('dh17_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('ec17_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('se14_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    if (item.typeId.endsWith('westar35_dual')) {
                        item.setLore(['§rammo: 0', 'Dual Blaster Pistol'])
                    };
                    player.getComponent("inventory").container.setItem(player.selectedSlot, item);
                }
            };
                await player.runCommandAsync(`scoreboard players set @s ammo ${item.getLore()[0].replace('§rammo: ', '')}`)
            }
                
        }
        
        lastSlotData.set( player.id, nowSlot )
    
    })
   } catch(error) {console.warn(error, error.stack)}
}

system.runSchedule( checkSlot, 4 );


let hitPosition = 0


function particle({location,dimension}) {
    let {x,y,z} = location
    dimension.spawnParticle('id:sparks',new Location(x,y,z), new MolangVariableMap());
    dimension.spawnParticle(`id:${hitPosition}`,new Location(x,y,z), new MolangVariableMap());
    world.playSound( "projectile.hit", { location: new Location(x,y,z)
      } )
}

let projectileType = 0

world.events.projectileHit.subscribe((hit) => {
    if (hit.projectile.typeId.endsWith('_projectile')){
    hitPosition = hit.blockHit.face
    projectileType = hit.projectile
    particle(hit);
    }
})


function randomizeVector ({ x, y, z }, min, max) {
    let d = max - min
    
    x += min + d * Math.random()
    y += min + d * Math.random()
    z += min + d * Math.random()
    
    return { x, y, z }
}



function getBulletDataFromConfig ({ origin, direction, inaccuracy = 1, height = 0, distance = 0 }) {
    let offset = inaccuracy
    let { x, y, z } = randomizeVector( direction, -offset, offset )
    
    let vector = new Vector( x, y, z )
    
    let location = new Location( 
        origin.x + x * distance,
        origin.y + y * distance + height,
        origin.z + z * distance
    )
    
    let max = 89.89999389648438
    
    let asinLimit = 90/90
    let yClamped = (y < -asinLimit) 
        ? -asinLimit
        : (y > asinLimit)
            ? asinLimit
            : y
    
    let clamp = (a,v,b) => Math.max( a, Math.min(v, b) );
    
    yClamped = clamp( -1, y, 1 )
    
    let degreesInRadian = 180 / Math.PI
    
    let rotation = {
        x: clamp( -max, degreesInRadian * Math.asin( -yClamped ), max ),
        y: degreesInRadian * Math.atan2( -x, z )
    }
    
    return {
        vector, location, rotation
    }
}


function attachmentForm (evplayer) {
    const attachmentform = new ActionFormData()
  .title("Attachments")
  .body("available")

const inv = evplayer.getComponent("inventory").container
const itemList = []
for (let i = 0; i < inv.size; i++) {
  const item = inv.getItem(i)
  if (!item) continue;

  if (
    item.typeId.startsWith("minecraft:") &&
    !itemList.includes(item.typeId)
  ) {
    attachmentform.button(item.typeId)
    itemList.push(item.typeId)
  }
}

attachmentform.show(evplayer).then(response => {
  evplayer.runCommandAsync(`say ${itemList[response.selection]}`);
})
}

let fire = false

let reload = 0

world.events.itemStartCharge.subscribe(ev => {
const form = new ActionFormData()
  .title("Item Type")
  .body("Form")
  .button("Scope Attachments")
  .button("Light/Laser Attachments right side")
  .button("Light/Laser Attachments left side")
  .button("Front Grip Attachments")

let evplayer = ev.source

form.show(evplayer).then(response => {
  if (response.selection === 0) {
      attachmentForm(evplayer);
  }
})
//_
    if (!ev.itemStack.typeId.includes('sw:')) return;
    const { item, source: player } = ev;
    const { dimension, viewVector, location, isSneaking } = player;
    const inventory = ev.source.getComponent('minecraft:inventory').container;
    const itemm = inventory.getItem(ev.source.selectedSlot);
    itemm.triggerEvent('test:test');
    let bulletData = getBulletDataFromConfig( {
        origin: location,
        direction: viewVector,
        height: 1.37,
        distance: 1,
        inaccuracy: isSneaking ? 0.2: 0.1
    } )
    
    let { vector, location: bulletLocation, rotation } = bulletData
    
    let entity = dimension.spawnEntity( `sw:dc15s_projectile`, bulletLocation );
    dimension.spawnParticle(`sw:mussleflash_blue`, bulletLocation, new MolangVariableMap());
    
    entity.setVelocity( Vector.multiply( vector, 0.5 ) );
    entity.setRotation( -rotation.x, -rotation.y );
    fire = true
    reload = system.runSchedule( () => {
    if (fire == false) {
        system.clearRunSchedule(reload);
    }
    if (fire == true) {
    try {
    const { dimension, viewVector, location, isSneaking } = player;
    
    let bulletData = getBulletDataFromConfig( {
        origin: location,
        direction: viewVector,
        height: 1.37,
        distance: 1,
        inaccuracy: isSneaking ? 0.2: 0.0
    } )
    
    let { vector, location: bulletLocation, rotation } = bulletData
    
    let entity = dimension.spawnEntity( `sw:dc15s_projectile`, bulletLocation );
    dimension.spawnParticle(`sw:mussleflash_blue`, bulletLocation, new MolangVariableMap());
    
    entity.setVelocity( Vector.multiply( vector, 0.5 ) );
    entity.setRotation( -rotation.x, -rotation.y );
    
    
    } catch(e) { 
        world.say('e') 
    }
    }
    }, 4)
})

world.events.itemStopCharge.subscribe(stopev => {
    const item = stopev.itemStack
    if (item.typeId.startsWith('sw:')) {
        system.clearRunSchedule(reload);
        fire = false
        console.warn('stop_use')
    }
})

//cancel crash

system.events.beforeWatchdogTerminate.subscribe((event)=>{event.cancel=true})

system.runSchedule(() => {
  for (const player of world.getAllPlayers()) {
    const { x, y, z } = player.viewVector;
    player.onScreenDisplay.setActionBar(`x: ${90 * x}, y: ${90 * y}, z: ${90 * z}`);
  }
});