import { defineTrait } from '../define.js';

export const pressable = defineTrait({
  name: 'pressable',
  category: 'input-interaction',
  description: 'Normalizes click/tap/keyboard into a single "press" event',
  attributes: ['data-pressable-pressed'],
  events: ['press'],
  config: [],
  setup({ host }) {
    let pressed = false;

    function isDisabled() {
      return host.hasAttribute('disabled');
    }

    function setPressed(value) {
      pressed = value;
      if (value) {
        host.setAttribute('data-pressable-pressed', '');
      } else {
        host.removeAttribute('data-pressable-pressed');
      }
    }

    function onPointerDown(e) {
      if (isDisabled()) return;
      setPressed(true);
    }

    function onPointerUp(e) {
      if (!pressed) return;
      setPressed(false);
      if (!isDisabled()) {
        host.dispatchEvent(new CustomEvent('press', { bubbles: true }));
      }
    }

    function onPointerLeave(e) {
      if (pressed) setPressed(false);
    }

    function onKeyDown(e) {
      if (isDisabled()) return;
      if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        setPressed(true);
      }
    }

    function onKeyUp(e) {
      if (!pressed) return;
      if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        setPressed(false);
        if (!isDisabled()) {
          host.dispatchEvent(new CustomEvent('press', { bubbles: true }));
        }
      }
    }

    host.addEventListener('pointerdown', onPointerDown);
    host.addEventListener('pointerup', onPointerUp);
    host.addEventListener('pointerleave', onPointerLeave);
    host.addEventListener('keydown', onKeyDown);
    host.addEventListener('keyup', onKeyUp);

    return () => {
      host.removeEventListener('pointerdown', onPointerDown);
      host.removeEventListener('pointerup', onPointerUp);
      host.removeEventListener('pointerleave', onPointerLeave);
      host.removeEventListener('keydown', onKeyDown);
      host.removeEventListener('keyup', onKeyUp);
      host.removeAttribute('data-pressable-pressed');
    };
  },
});
