from __future__ import annotations

import sys
from pathlib import Path


ROOT = next(parent for parent in Path(__file__).resolve().parents if (parent / "cosmic_driver").is_dir())
sys.path.insert(0, str(ROOT))

from cosmic_driver import CosmicPySDK, FW_I2C_BUS_WITH_NO_TARGETS_CONNECTED, FW_INTERFACE_ALREADY_INITIALIZED, I2cBus, I2cPullUp, SUCCESS
from example_helpers import print_device_info, print_payload, assert_status


def main() -> None:
    with CosmicPySDK(timeout_ms=2000) as device:
        if not device.open():
            raise RuntimeError("Failed to connect to a Binho device.")

        status, info = device.get_device_info()
        assert_status(status, "get_device_info")
        assert info is not None
        print_device_info(info)

        status, _ = device.i2c_set_bus_voltage(3300, False)
        assert_status(status, "i2c_set_bus_voltage")

        status, _ = device.i2c_controller_init(I2cBus.I2C_BUS_A, 200000, I2cPullUp.I2C_PULLUP_330Ohm)
        assert_status(status, "i2c_controller_init", (SUCCESS, FW_INTERFACE_ALREADY_INITIALIZED))

        status, _ = device.i2c_set_parameters(I2cBus.I2C_BUS_A, 200000, I2cPullUp.I2C_PULLUP_330Ohm)
        assert_status(status, "i2c_set_parameters")

        status, _ = device.i2c_set_pull_up_resistors(I2cBus.I2C_BUS_A, I2cPullUp.I2C_PULLUP_1_5kOhm)
        assert_status(status, "i2c_set_pull_up_resistors")

        target_address = 0x50
        subaddress = [0x01, 0x00]
        transfer_length = 128
        write_payload = [0xAA] * transfer_length

        status, _ = device.i2c_write(I2cBus.I2C_BUS_A, target_address, subaddress, write_payload, True)
        assert_status(status, "i2c_write(non-stop)")
        status, read_payload = device.i2c_read(I2cBus.I2C_BUS_A, target_address, subaddress, transfer_length, True)
        assert_status(status, "i2c_read(non-stop)")
        assert read_payload is not None
        if read_payload != write_payload:
            raise RuntimeError("Non-stop write/read verification failed.")
        print_payload("Non-stop payload:", read_payload)

        write_payload = [0xFF] * transfer_length
        status, _ = device.i2c_write(I2cBus.I2C_BUS_A, target_address, subaddress, write_payload, False)
        assert_status(status, "i2c_write")
        status, read_payload = device.i2c_read(I2cBus.I2C_BUS_A, target_address, subaddress, transfer_length, False)
        assert_status(status, "i2c_read")
        assert read_payload is not None
        if read_payload != write_payload:
            raise RuntimeError("Write/read verification failed.")
        print_payload("Standard payload:", read_payload)

        status, scan_result = device.i2c_scan_bus(I2cBus.I2C_BUS_A, 128, True)
        assert_status(
            status,
            "i2c_scan_bus",
            (SUCCESS, FW_I2C_BUS_WITH_NO_TARGETS_CONNECTED),
        )
        if scan_result is not None:
            print("7-bit Address devices:")
            for address in scan_result.addresses_7bit:
                print(f"\t0x{address:02X}")
            print("10-bit Address devices:")
            for address in scan_result.addresses_10bit:
                print(f"\t0x{address:04X}")


if __name__ == "__main__":
    main()
