/*
hello dear add-on maker. want to use my code? sure. but it would probably help if you understand how it works instead of
just copy pasting it and changing ids...

the code shouldnt be too hard to understand. should be easy to configure for your own things

but if you're mostly just using the same code, would be nice if you credit

note that this custom death message code is janky and does not account for explosion kills.
the code doesnt work 100% of the time and is meant to only show for player kills using the guns in SCP: OP
the custom death messages in the upcoming SCP: Collaboration Remake works better

hit me up if you found a better way to make death messages pls i need help lol
and there's also no current way that i know of to detect certain forms of damage like warden sonic boom.

- JuliusScizzor
*/


import {
    world,
    Player,
    system,
    Vector,
    EntityDamageCause,
    EntityHealthComponent,
    Entity,
} from "@minecraft/server";

import { projectileDef } from "./customProjectileDamage";


function randomMessage(messages, ...replace) {
  const idx = Math.floor(Math.random() * messages.length);
  let msg = messages[idx];
  for (let i = 1; i <= replace.length; i++) {
    msg = msg.replace(`$${i}`, replace[i - 1]);
  }
  return msg;
}


world.afterEvents.playerSpawn.subscribe(({ player }) => {
  player.lastHit = undefined;
});

let projectileId

let explosionDamager;
world.beforeEvents.explosion.subscribe((data) => {
  const explosionHitter = data.source.typeId;
  explosionDamager = explosionHitter;
});


const LastHitThreshold = 300;
let lastProcessedTick = -1;

world.afterEvents.entityHurt.subscribe(({ hurtEntity, damageSource }) => {
  if (system.currentTick === lastProcessedTick) {
    return;
  }
  lastProcessedTick = system.currentTick; 
  
    const health = (hurtEntity.getComponent("health"));
    const hitterProjectile = hurtEntity.lastHit?.projectile
    const hitter = hurtEntity.lastHit?.hitter
    const deadEntityName = hurtEntity.name
    const damageCause = damageSource.cause

    if (damageCause == "entityExplosion" && damageCause != "projectile") {
      hurtEntity.lastHit = {
        hitter: explosionDamager,
        tick: system.currentTick,
      }
    } else if (damageCause == "projectile" && damageCause != "entityExplosion") {
        world.afterEvents.entitySpawn.subscribe(({ entity }) => {
          const type = entity.typeId
              projectileId = type
              const callback = world.afterEvents.projectileHit.subscribe((arg) => {
                  world.afterEvents.projectileHit.unsubscribe(callback)
                  const { source, projectile } = arg
                  const hitInfo = arg.getEntityHit()

                  if (hitInfo && (projectile === entity)) {
                      const hurtEntity = hitInfo.entity
                      hurtEntity.lastHit = {
                        hitter: source.name ?? source.typeId,
                        projectile: projectileId,
                        tick: system.currentTick,
                      }
                     // world.sendMessage(`entity ${hurtEntity.lastHit.hitter} proj ${hurtEntity.lastHit.projectile}  hitter ${hurtEntity.lastHit.hitter}`)
                  }
              })
        })
    } else {
      if (damageSource.damagingEntity instanceof Player) {
        hurtEntity.lastHit = {
            hitter: damageSource.damagingEntity.name,
            tick: system.currentTick,
          }
         // world.sendMessage(`${damageSource.damagingEntity.typeId} plater`)
      } else if (damageSource.damagingEntity instanceof Entity) {
        hurtEntity.lastHit = {
          hitter: damageSource.damagingEntity.typeId,
          tick: system.currentTick,
        }
       // world.sendMessage(`${hurtEntity.lastHit.hitter} wbreuw`)
      } 
    }
    if (health.currentValue > 0) return
    
    let hitterI = hurtEntity.lastHit?.hitter

    if (hitterProjectile) {
      const projDef = projectileDef[hitterProjectile];
      if (projDef && hurtEntity.hasTag("friendly_fire_on")) {
        const deathMsgDef = projDef.deathMessage;
        const messages = deathMsgDef.messages;
        const randomIndex = Math.floor(Math.random() * messages.length);
        const selectedMessage = messages[randomIndex];
        world.sendMessage(`${deadEntityName} was ${selectedMessage} by ${hitter} using ${deathMsgDef.weapon}`);
        }
      }
  },
  { entityTypes: ["minecraft:player"] }
);

  
  const MESSAGES = {
    default: {
      noAttacker: [`$1 died`, `$1 died`, `$1 died`, `$1 died`, `$1 died`, `$1 passed away`, `$1 passed away`, `$1 passed away`, `$1 passed away`, `$1 defied god`],
      withAttacker: [`$1 died`, `$1 died`, `$1 died`, `$1 died`, `$1 died`, `$1 passed away`, `$1 passed away`, `$1 passed away`, `$1 passed away`, `$1 defied god`],
    },
    anvil: {
      noAttacker: [
        `$1 was squashed by a falling anvil`,
        `$1 was crushed by an anvil from above`,
        `$1 was flattened by a heavy anvil`,
      ],
      withAttacker: [
        {
          messages: [
            `$1 was squashed by a falling anvil whilst trying to escape $2`,
            `$1 was crushed by an anvil from above whilst trying to escape $2`,
            `$1 was flattened by a heavy anvil whilst trying to escape $2`,
          ],
        },
      ],
    },
    blockExplosion: {
      noAttacker: [
        `$1 was killed by [Intentional Game Design]`,
        `$1 was absolutely kaboozled into a million pieces`,
      ],
      withAttacker: [
        {
          messages: [
            `$1 was killed by [Intentional Game Design] whilst trying to escape $2`,
            `$1 was absolutely kaboozled into a million pieces whilst trying to escape $2`,
          ],
        },
      ],
    },
    entityAttack: {
      withAttacker: [
        {
          typeId: 'scp610_1',
          messages: [
            `$1 was punched to death by $2`,
            `$1 was sucker-punched to death by $2`,
          ],
        },
        {
          typeId: 'scp610_2',
          messages: [
            `$1 was chomped by $2`,
            `$1 was mauled by $2`,
          ],
        },
        {
          typeId: 'scp610_9',
          messages: [
            `$1 was eaten alive by $2`,
          ],
        },
        {
          typeId: 'scp610_9_1',
          messages: [
            `$1 was munched to death by $2`,
            `$1 was munched to death by $2`,
            `$1 was munched to death by $2`,
            `$1 was munched to death by LITTLE BUGGER`,
            `$1 became sustenance for $2`,
            `$1 became sustenance for $2`,
            `$1 became sustenance for $2`,
            `$1 became sustenance for LITTLE BUGGER`,
          ],
        },
        {
          typeId: 'scp610_12',
          messages: [
            `$1 was eviscerated by $2`,
          ],
        },
        {
          messages: [
            `$1 was slain by $2`,
            `$1 was slain by $2`,
            `$1 was slain by $2`,
            `$1 was killed by $2`,
            `$1 was exterminated by $2`,
            `$1 was slaughtered by $2`,
            `$1 was eliminated by $2`,
          ],
        },
      ],
      noAttacker: [ `$1 was slain`, ],
    },
    entityExplosion: {
      withAttacker: [
        {
          typeId: 'scp610_1',
          messages: [
            `$1 smashed into bits by $2`,
            `$1 crushed into oblivion by $2`,
          ],
        },
        {
          typeId: 'scp610_2',
          messages: [
            `$1 was engulfed in toxic fumes from the spontaneous explosion of $2`,
          ],
        },
        {
          typeId: 'impact_grenade',
          messages: [
            `$1 was blown up by an $2`,
            `$1 was kabmloomied into pieces by an $2`,
            `$1 blew up into smithereens due to an $2`,
          ],
        },
        {
          typeId: 'hand_grenade',
          messages: [
            `$1 was blown up by a $2`,
            `$1 was kabmloomied into pieces by a $2`,
            `$1 stood too close to a $2`,
          ],
        },
        {
          typeId: 'mine',
          messages: [
            `$1 was discombobulated by a $2`,
            `$1 stepped on a $2`,
            `$1 did not see that $2 coming`,
            `$1 blew up into smithereens due to a $2`,
          ],
        },
        {
          typeId: 'acid_ball_explode',
          messages: [
            `$1 was acified by a $2`,
            `$1 melted into a puddle by a $2`,
          ],
        },
        {
          messages: [
            `$1 was blown up by $2`,
            `$1 was kabmloomied into pieces by $2`,
            `$1 blew up into smithereens in the hands of $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 blew up into smithereens`,
          `$1 was kabloomied into pieces`,
      ],
    },
    charging: {
      withAttacker: [
        {
          messages: [
              `$1 was knocked out by a charge by $2`,
              `$1 was charged at by $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 was charged to death`,
      ],
    },
    contact: {
      withAttacker: [
        {
          messages: [
              `$1 was tickled to death by a cactus whilst trying to escape $2`,
              `$1 got a little too close to a cactus whilst trying to escape $2`,
              `$1 was pricked to death by a cactus whilst trying to escape $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 was tickled to death by a cactus`,
          `$1 got a little too close to a cactus`,
          `$1 was pricked to death by a cactus`,
      ],
    },
    drowning: {
      withAttacker: [
        {
          messages: [
              `$1 drowned whilst trying to escape $2`,
              `$1 was enlightened that they are not a fish by $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 drowned`,
          `$1 found out they weren't a fish`,
          `$1 thought they were a fish`,
          `$1 stayed underwater too long`,
      ],
    },
    fall: {
      withAttacker: [
        {
          messages: [
              `$1 fell from a high place whilst trying to escape $2`,
              `$1 was doomed to fall whilst trying to escape $2`,
              `$1 had their knees broken by $2`,
              `$1 had their ankles broken by $2`,
              `$2 wished $1 to break a leg, and they did`,
              `$1 was pushed off a cliff by $2`,
              `$1 was knocked off the edge of a very high place by $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 fell from a high place`,
          `$1 broke their knees`,
          `$1 broke their ankles`,
          `$1 shattered their feet`,
          `$1 hit the ground too hard`,
          `$1 broke a leg`,
          `$1 tripped and fell`,
      ],
    },
    fallingBlock: {
      withAttacker: [
        {
          messages: [
              `$1 had a block fall on their head because of $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 had a block fall on their head`,
      ],
    },
    fire: {
      withAttacker: [
        {
          messages: [
              `$1 walked into fire whilst fighting $2`,
              `$1 was burnt to a crisp whilst fighting $2`,
              `$1 was warmed too much by $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 went up in flames`,
          `$1 burned to death`,
          `$1 turned into ash`,
          `$1 burnt into a crisp`,
      ],
    },
    fireTick: {
      withAttacker: [
        {
          messages: [
              `$1 walked into fire whilst fighting $2`,
              `$1 was burnt to a crisp whilst fighting $2`,
              `$1 was warmed too much by $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 went up in flames`,
          `$1 burned to death`,
          `$1 turned into ash`,
          `$1 burnt into a crisp`,
      ],
    },
    fireworks: {
      withAttacker: [
        {
          messages: [
              `$1 went off with a bang due to a firework fired by $2`,
              `$1 was kabloomied by a firework fired by $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 went off with a bang`,
          `$1 was kabloomied by a firework`,
      ],
    },
    flyIntoWall: {
      withAttacker: [
        {
          messages: [
              `$1 experienced kinetic energy whilst trying to escape from $2`,
              `$1 splatted into a wall whilst trying to escape from $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 experienced kinetic energy`,
          `$1 splatted into a wall`,
      ],
    },
    freezing: {
      withAttacker: [
        {
          messages: [
              `$1 froze to death whilst trying to escape from $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 froze to death`,
      ],
    },
    lava: {
      withAttacker: [
        {
          messages: [
              `$1 tried to swim in lava whilst trying to escape from $2`,
              `$1 was given a nice warm bath in lava by $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 tried to swim in lava`,
          `$1 had a little too nice of a bath in lava`,
      ],
    },
    lightning: {
      withAttacker: [
        {
          typeId: 'teslagate',
          messages: [
            `$1 was electrocuted while running through a $2`,
            `$1 was electrocuted by a $2`,
            `$1 stood too close to a $2`,
          ],
        },
        {
          messages: [
              `$1 was smited by lightning whilst fighting $2`,
              `Zeus decided to end $1 instead of $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 was struck by lightning`,
          `$1 had a bad day with Zeus`,
          `Zeus did not like $1`,
      ],
    },
    magic: {
      withAttacker: [
        {
          typeId: 'scp610_10',
          messages: [
            `$1 was melted into a puddle by $2`,
          ],
        },
        {
          typeId: 'acid_puddle',
          messages: [
            `$1 was absorbed into an $2`,
          ],
        },
        {
          messages: [
              `$1 was killed by magic whilst trying to escape $2`,
              `$1 was killed by $2 using magic`,
              `$2 performed a magic trick on $1`,
          ],
        },
      ],
      noAttacker: [
          `$1 was killed by magic`,
          `$1 experienced a magic trick`,
      ],
    },
    magma: {
      withAttacker: [
        {
          messages: [
              `$1 was bamboozled by the floor whilst trying to escape $2`,
              `$1 discovered floor was lava whilst trying to escape $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 discovered floor was lava`,
          `$1 was bamboozled by the floor`,
      ],
    },
    none: {
      withAttacker: [
        {
          messages: [
              `$1 was somehow killed by nothing because of $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 died for some reason`,
          `$1 died for no reason`,
      ],
    },
    override: {
      withAttacker: [
        {
          messages: [
              `$1 had their life overridden by $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 had their life overridden`,
      ],
    },
    piston: {
      withAttacker: [
        {
          typeId: 'blastdoor',
          messages: [
            `$1 was crushed between a $2`,
            `$1 got stuck in between a $2`,
            `$1 was squashed by a $2`,
          ],
        },
        {
          typeId: 'lcdoor',
          messages: [
            `$1 was crushed between a $2`,
            `$1 got stuck in between a $2`,
            `$1 was squashed by a $2`,
          ],
        },
        {
          typeId: 'hcdoor',
          messages: [
            `$1 was crushed between a $2`,
            `$1 got stuck in between a $2`,
            `$1 was squashed by a $2`,
          ],
        },
        {
          messages: [
              `$1 was squashed by a piston in the hands of $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 was squashed by a piston`,
      ],
    },
    projectile: {
      withAttacker: [
        {
          typeId: 'arrow',
          messages: [
            `$1 was shot by $2`,
            `$1 was sniped by $2`,
          ],
        },
        {
          typeId: 'thrown_trident',
          messages: [
            `$1 was impaled to death by $2`,
          ],
        },
        {
          typeId: 'fireball',
          messages: [
            `$1 was blown up byz $2`,
          ],
        },
        {
          messages: [
            `$1 was shot by $2`,
            `$1 was hit with a very fast flying object from $2`,
          ],
        },
      ],
      noAttacker: [
        `$1 was shot`,
        `$1 was hit with a very fast flying object`,
      ],
    },
    stalactite: {
      withAttacker: [
        {
          messages: [
              `$1 was skewered by a falling stalactite whilst fighting $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 was skewered by a falling stalactite`,
      ],
    },
    stalagmite: {
      withAttacker: [
        {
          messages: [
              `$1 was impaled on a stalagmite whilst trying to escape $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 was impaled on a stalagmite`,
      ],
    },
    starve: {
      withAttacker: [
        {
          messages: [
              `$1 starved to death whilst fighting $2`,
              `$1 forgot to eat for too long whilst fighting $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 starved to death`,
          `$1 forgot eat for too long`,
      ],
    },
    suffocation: {
      withAttacker: [
        {
          messages: [
              `$1 suffocated in a wall whilst trying to escape $2`,
              `$1 was smothered to death whilst fighting $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 suffocated in a wall`,
          `$1 was smothered to death`,
      ],
    },
    suicide: {
      withAttacker: [
        {
          messages: [
              `$1 was sent off by $2`,
              `$1 did not want to live in the same world as $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 game ended themself`,
          `$1 did not want to live in this world`,
          `$1 met god`,
      ],
    },
    temperature: {
      withAttacker: [
        {
          messages: [
              `$1 succumbed to the effects of climate change as a result of humanity's, but more specifically, $2's actions`,
          ],
        },
      ],
      noAttacker: [
          `$1 succumed to the effects of climate change as a result of humanity's actions`,
      ],
    },
    thorns: {
      withAttacker: [
        {
          messages: [
              `$1 was killed trying to hurt $2`,
              `$2 played an uno reverse card on $1`,
          ],
        },
      ],
      noAttacker: [
          `$1 was uno reversed`,
      ],
    },
    void: {
      withAttacker: [
        {
          messages: [
              `$1 fell out of the world whilst trying to escape $2`,
              `$1 left the world whilst trying to escape $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 fell out of the world`,
          `$1 fell off`,
          `$1 left`,
      ],
    },
    wither: {
      withAttacker: [
        {
          messages: [
              `$1 withered away whilst trying to escape $2`,
          ],
        },
      ],
      noAttacker: [
          `$1 withered away`,
      ],
    },
  };
