import { ptr } from "bun:ffi"
import {
  GPIOD_LINE_BIAS_PULL_UP,
  GPIOD_LINE_BIAS_PULL_DOWN,
  GPIOD_LINE_BIAS_DISABLED,
  GPIOD_LINE_EDGE_RISING,
  GPIOD_LINE_EDGE_FALLING,
  GPIOD_LINE_EDGE_BOTH,
  GPIOD_EDGE_EVENT_RISING_EDGE,
  GPIOD_EDGE_EVENT_FALLING_EDGE,
} from "./ffi"
import type { PullMode, EdgeMode } from "./types"

export const cstr = (s: string) => ptr(Buffer.from(s + "\0"))

export const mapPullToLibgpiod = (pull: PullMode): number => {
  switch (pull) {
    case "up":
      return GPIOD_LINE_BIAS_PULL_UP
    case "down":
      return GPIOD_LINE_BIAS_PULL_DOWN
    case "none":
      return GPIOD_LINE_BIAS_DISABLED
  }
}

export const mapEdgeToLibgpiod = (edge: EdgeMode): number => {
  switch (edge) {
    case "rising":
      return GPIOD_LINE_EDGE_RISING
    case "falling":
      return GPIOD_LINE_EDGE_FALLING
    case "both":
      return GPIOD_LINE_EDGE_BOTH
  }
}

// Hardware logic:
// - Pull-up + button to GND: pressing pulls line LOW (falling edge = pressed)
// - Pull-down + button to VCC: pressing pulls line HIGH (rising edge = pressed)
export const mapLibgpiodEdgeToPressedState = (edgeType: number, pull: PullMode): boolean => {
  if (pull === "up") {
    return edgeType === GPIOD_EDGE_EVENT_FALLING_EDGE
  } else if (pull === "down") {
    return edgeType === GPIOD_EDGE_EVENT_RISING_EDGE
  } else {
    return edgeType === GPIOD_EDGE_EVENT_RISING_EDGE
  }
}

export const hashInputConfig = (pull: PullMode, debounce: number, edge: EdgeMode): string => {
  return `${pull}-${debounce}-${edge}`
}
