import {
  world,
  BlockPermutation
} from "@minecraft/server";

const processedBlocks = new Map();

world.beforeEvents.worldInitialize.subscribe(initEvent => {
  initEvent.blockComponentRegistry.registerCustomComponent('we:door_interact', {
    onPlayerInteract(e) {
      const {
        block
      } = e;
      const isUpperBlock = block.permutation.getState('we:upper_block_bit');

      const targetBlock = isUpperBlock ? block.below() : block.above();

      const currentOpenState = block.permutation.getState('we:open_bit');
      const targetOpenState = targetBlock.permutation.getState('we:open_bit');

      const newOpenState = !currentOpenState;
      const newTargetOpenState = !targetOpenState;

      const newBlockPermutation = BlockPermutation.resolve(block.typeId, {
        ...block.permutation.getAllStates(),
        'we:open_bit': newOpenState
      });

      const newTargetBlockPermutation = BlockPermutation.resolve(targetBlock.typeId, {
        ...targetBlock.permutation.getAllStates(),
        'we:open_bit': newTargetOpenState
      });

      block.setPermutation(newBlockPermutation);
      targetBlock.setPermutation(newTargetBlockPermutation);

      const sound = currentOpenState ? 'close.cherry_wood_door' : 'open.cherry_wood_door';

      e.dimension.playSound(sound, block.center());

    }
  });

  initEvent.blockComponentRegistry.registerCustomComponent('we:door_place', {
    beforeOnPlayerPlace(e) {

      const above = e.block.above();

      if(!above.isAir) {
        e.cancel = true;
      }

    },
    onPlace(e) {
      // Destructure event data for easier access
      const {
        block
      } = e;
      const aboveBlock = block.above();
      const northBlock = block.north(); // Get the block to the east
      const southBlock = block.south(); // Get the block to the east
      const eastBlock = block.east(); // Get the block to the east
      const westBlock = block.west(); // Get the block to the east
      const {
        x,
        y,
        z
      } = block.location;

      // Check if the block has already been processed
      if (processedBlocks.has(`${x},${y},${z}`)) {
        return;
      }

      const currentStates = block.permutation.getAllStates();

      const cardinalDirection = currentStates['minecraft:cardinal_direction'];

      if (aboveBlock.typeId === 'minecraft:air' && !block.permutation.getState('we:upper_block_bit')) {

        const aboveBlockPermutation = BlockPermutation.resolve(block.typeId, {
          'we:upper_block_bit': true,
          'minecraft:cardinal_direction': cardinalDirection
        });
        aboveBlock.setPermutation(aboveBlockPermutation);

        const newPermutation = BlockPermutation.resolve(block.typeId, currentStates);

        block.setPermutation(newPermutation);
      }

      if (cardinalDirection === 'south' && eastBlock?.hasTag('we:door')) {
        const eastBlockStates = eastBlock.permutation.getAllStates();

        if (!eastBlockStates['we:hinge_bit']) {

          const newPermutation = BlockPermutation.resolve(block.typeId, {
            ...currentStates,
            'we:hinge_bit': true
          });
          block.setPermutation(newPermutation);
        }

        const aboveBlockCardinalDirection = aboveBlock.permutation.getState('minecraft:cardinal_direction');
        const eastBlockAbove = aboveBlock.east();
        if (
          aboveBlockCardinalDirection === 'south' &&
          eastBlockAbove?.hasTag('we:door')
        ) {
          const eastBlockAboveStates = eastBlockAbove.permutation.getAllStates();

          if (!eastBlockAboveStates['we:hinge_bit']) {

            const newAbovePermutation = BlockPermutation.resolve(aboveBlock.typeId, {
              ...eastBlockAboveStates,
              'we:hinge_bit': true
            });
            aboveBlock.setPermutation(newAbovePermutation);
          }
        }
      }

      if (cardinalDirection === 'east' && northBlock?.hasTag('we:door')) {
        const northBlockStates = northBlock.permutation.getAllStates();

        if (!northBlockStates['we:hinge_bit']) {

          const newPermutation = BlockPermutation.resolve(block.typeId, {
            ...currentStates,
            'we:hinge_bit': true
          });
          block.setPermutation(newPermutation);
        }
        const aboveBlockCardinalDirection = aboveBlock.permutation.getState('minecraft:cardinal_direction');
        const northBlockAbove = aboveBlock.north();
        if (
          aboveBlockCardinalDirection === 'east' &&
          northBlockAbove?.hasTag('we:door')
        ) {
          const northBlockAboveStates = northBlockAbove.permutation.getAllStates();

          if (!northBlockAboveStates['we:hinge_bit']) {

            const newAbovePermutation = BlockPermutation.resolve(aboveBlock.typeId, {
              ...northBlockAboveStates,
              'we:hinge_bit': true
            });
            aboveBlock.setPermutation(newAbovePermutation);
          }
        }
      }

      if (cardinalDirection === 'north' && westBlock?.hasTag('we:door')) {
        const westBlockStates = westBlock.permutation.getAllStates();

        if (!westBlockStates['we:hinge_bit']) {

          const newPermutation = BlockPermutation.resolve(block.typeId, {
            ...currentStates,
            'we:hinge_bit': true
          });
          block.setPermutation(newPermutation);
        }

        const aboveBlockCardinalDirection = aboveBlock.permutation.getState('minecraft:cardinal_direction');
        const westBlockAbove = aboveBlock.west();
        if (
          aboveBlockCardinalDirection === 'north' && westBlockAbove.hasTag('we:door')) {
          const westBlockAboveStates = westBlockAbove.permutation.getAllStates();

          if (!westBlockAboveStates['we:hinge_bit']) {

            const newAbovePermutation = BlockPermutation.resolve(aboveBlock.typeId, {
              ...westBlockAboveStates,
              'we:hinge_bit': true
            });
            aboveBlock.setPermutation(newAbovePermutation);
          }
        }
      }

      if (cardinalDirection === 'west' && southBlock?.hasTag('we:door')) {
        const southBlockStates = southBlock.permutation.getAllStates();

        if (!southBlockStates['we:hinge_bit']) {
          const newPermutation = BlockPermutation.resolve(block.typeId, {
            ...currentStates,
            'we:hinge_bit': true
          });
          block.setPermutation(newPermutation);
        }
        const aboveBlockCardinalDirection = aboveBlock.permutation.getState('minecraft:cardinal_direction');
        const southBlockAbove = aboveBlock.south();
        if (
          aboveBlockCardinalDirection === 'west' &&
          southBlockAbove?.hasTag('we:door')
        ) {
          const southBlockAboveStates = southBlockAbove.permutation.getAllStates();
          if (!southBlockAboveStates['we:hinge_bit']) {
            const newAbovePermutation = BlockPermutation.resolve(aboveBlock.typeId, {
              ...southBlockAboveStates,
              'we:hinge_bit': true
            });
            aboveBlock.setPermutation(newAbovePermutation);
          }
        }
      }
      processedBlocks.set(`${x},${y},${z}`, true);
    }
  });
});

world.afterEvents.playerBreakBlock.subscribe(eventData => {
  const {
    block
  } = eventData;
  const {
    x,
    y,
    z
  } = block.location;

  processedBlocks.delete(`${x},${y},${z}`);

  const aboveBlock = block.above();
  const belowBlock = block.below();
  if (belowBlock.hasTag('we:door')) {
    belowBlock.setType('minecraft:air');
    processedBlocks.delete(`${x},${y-1},${z}`);

  } else if (aboveBlock.hasTag('we:door')) {
    aboveBlock.setType('minecraft:air');
    processedBlocks.delete(`${x},${y+1},${z}`);
  }
});