function onDelegatedClick(
  selector: string,
  handler: (element: HTMLElement, event: MouseEvent) => void,
): void {
  document.addEventListener("click", (event: MouseEvent) => {
    const target = event.target as HTMLElement;
    const element = target.closest(selector) as HTMLElement | null;
    if (element) {
      handler(element, event);
    }
  });
}

function onDelegatedSubmit(
  selector: string,
  handler: (form: HTMLFormElement, event: Event) => void,
): void {
  document.addEventListener("submit", (event: Event) => {
    const target = event.target as HTMLElement;
    const form = target.closest(selector) as HTMLFormElement | null;
    if (form) {
      handler(form, event);
    }
  });
}

function onDelegatedChange(
  selector: string,
  handler: (element: HTMLElement, event: Event) => void,
): void {
  document.addEventListener("change", (event: Event) => {
    const target = event.target as HTMLElement;
    const element = target.closest(selector) as HTMLElement | null;
    if (element) {
      handler(element, event);
    }
  });
}

function onDelegatedKeydown(
  selector: string,
  handler: (element: HTMLElement, event: KeyboardEvent) => void,
): void {
  document.addEventListener("keydown", (event: KeyboardEvent) => {
    const target = event.target as HTMLElement;
    const element = target.closest(selector) as HTMLElement | null;
    if (element) {
      handler(element, event);
    }
  });
}

function getDataAttribute(
  element: HTMLElement,
  name: string,
): string | undefined {
  return element.dataset[name];
}

function setDataAttribute(
  element: HTMLElement,
  name: string,
  value: string,
): void {
  element.dataset[name] = value;
}

function onClick(
  element: HTMLElement | null,
  handler: (event: MouseEvent) => void,
): void {
  if (element) {
    element.addEventListener("click", handler);
  }
}

function onSubmit(
  element: HTMLFormElement | null,
  handler: (event: Event) => void,
): void {
  if (element) {
    element.addEventListener("submit", handler);
  }
}

function onChange(
  element: HTMLElement | null,
  handler: (event: Event) => void,
): void {
  if (element) {
    element.addEventListener("change", handler);
  }
}

function onKeydown(
  element: HTMLElement | null,
  handler: (event: KeyboardEvent) => void,
): void {
  if (element) {
    element.addEventListener("keydown", handler);
  }
}

function onInput(
  element: HTMLElement | null,
  handler: (event: Event) => void,
): void {
  if (element) {
    element.addEventListener("input", handler);
  }
}

function preventDefault(event: Event): void {
  event.preventDefault();
}

function stopPropagation(event: Event): void {
  event.stopPropagation();
}

export {
  getDataAttribute,
  onChange,
  onClick,
  onDelegatedChange,
  onDelegatedClick,
  onDelegatedKeydown,
  onDelegatedSubmit,
  onInput,
  onKeydown,
  onSubmit,
  preventDefault,
  setDataAttribute,
  stopPropagation,
};
