#ifndef PCA9956B_REGISTER_DRIVER_H
#define PCA9956B_REGISTER_DRIVER_H

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#define PCA9956B_CHANNELS_PER_CHIP 24u
#define PCA9956B_MAX_CHIPS 6u
#define PCA9956B_I2C_MAX_WRITE_BYTES 25u

typedef bool (*pca9956b_i2c_write_fn)(void *context, uint8_t address_7bit,
                                      const uint8_t *bytes, size_t length);
typedef bool (*pca9956b_pin_state_fn)(void *context);
typedef bool (*pca9956b_force_off_fn)(void *context);

/*
 * Callbacks must be bounded. write_transaction performs one complete I2C
 * START/address/register/data/STOP transaction and returns true only if every
 * byte was ACKed and STOP completed. The address is unshifted 7-bit form.
 * oe_n_is_high and led_rail_is_disabled must read actual pin/permit states,
 * not merely software's last commanded values.
 */
typedef struct {
    void *context;
    pca9956b_i2c_write_fn write_transaction;
    pca9956b_pin_state_fn oe_n_is_high;
    pca9956b_pin_state_fn led_rail_is_disabled;
    pca9956b_force_off_fn force_outputs_off;
} pca9956b_io;

typedef struct {
    pca9956b_io io;
    uint8_t chip_count;
    uint8_t address_7bit[PCA9956B_MAX_CHIPS];
    bool initialized;
    bool current_profile_loaded;
    bool fault_latched;
} pca9956b_driver;

/*
 * Must be called with OE_N high and the LED rail disabled. Initialization
 * clears all current/PWM registers, configures per-channel PWM control, and
 * leaves the device dark. A physical current profile is required before PWM
 * writes are accepted.
 */
bool pca9956b_init(pca9956b_driver *driver, const pca9956b_io *io,
                   const uint8_t *addresses_7bit, size_t chip_count);

/*
 * Writes chip_count * 24 explicit IREF register values, row-major by chip.
 * The caller must supply a profile approved against the selected REXT value,
 * LED ratings, thermal design, and measured optical target. This function
 * requires OE_N high and the LED rail disabled.
 */
bool pca9956b_apply_current_profile(pca9956b_driver *driver,
                                    const uint8_t *iref_values,
                                    size_t values_length);

/* Signature-compatible PWM callback for lamp_output_adapter.lg_output_io. */
bool pca9956b_write_chip_pwm(void *driver_context, uint8_t chip_index,
                             const uint8_t pwm[PCA9956B_CHANNELS_PER_CHIP]);

bool pca9956b_is_ready(const pca9956b_driver *driver);

#endif
