package com.binho.cosmicsdk.examples.i2c;

import com.binho.cosmicsdk.CosmicSdk;
import com.binho.cosmicsdk.ResultCodes;
import com.binho.cosmicsdk.Types.I2cBus;
import com.binho.cosmicsdk.Types.I2cPullUp;

import java.util.Arrays;

import static com.binho.cosmicsdk.examples.ExampleHelpers.assertStatus;
import static com.binho.cosmicsdk.examples.ExampleHelpers.printDeviceInfo;
import static com.binho.cosmicsdk.examples.ExampleHelpers.printPayload;

public final class I2cExample {
    private I2cExample() {
    }

    public static void main(String[] args) {
        try (CosmicSdk sdk = new CosmicSdk(2000)) {
            if (!sdk.connect()) {
                throw new IllegalStateException("Failed to connect to a Binho device.");
            }

            var infoResult = sdk.getDeviceInfo();
            assertStatus(infoResult.status(), "getDeviceInfo");
            printDeviceInfo(infoResult.value());

            assertStatus(sdk.i2cSetBusVoltage(3300, false), "i2cSetBusVoltage");
            assertStatus(
                    sdk.i2cControllerInit(I2cBus.I2C_BUS_A, 200000, I2cPullUp.I2C_PULLUP_330Ohm),
                    "i2cControllerInit",
                    ResultCodes.SUCCESS,
                    ResultCodes.FW_INTERFACE_ALREADY_INITIALIZED
            );
            assertStatus(sdk.i2cSetParameters(I2cBus.I2C_BUS_A, 200000, I2cPullUp.I2C_PULLUP_330Ohm), "i2cSetParameters");
            assertStatus(sdk.i2cSetPullUpResistors(I2cBus.I2C_BUS_A, I2cPullUp.I2C_PULLUP_1_5kOhm), "i2cSetPullUpResistors");

            byte[] subAddress = new byte[]{0x01, 0x00};
            byte[] writePayload = new byte[128];
            Arrays.fill(writePayload, (byte) 0xAA);

            assertStatus(sdk.i2cWrite(I2cBus.I2C_BUS_A, 0x50, subAddress, writePayload, true), "i2cWrite(non-stop)");
            var readNonStop = sdk.i2cRead(I2cBus.I2C_BUS_A, 0x50, subAddress, 128, true);
            assertStatus(readNonStop.status(), "i2cRead(non-stop)");
            if (!Arrays.equals(writePayload, readNonStop.value())) {
                throw new IllegalStateException("Non-stop write/read verification failed.");
            }
            printPayload("Non-stop payload:", readNonStop.value());

            Arrays.fill(writePayload, (byte) 0xFF);
            assertStatus(sdk.i2cWrite(I2cBus.I2C_BUS_A, 0x50, subAddress, writePayload, false), "i2cWrite");
            var readStandard = sdk.i2cRead(I2cBus.I2C_BUS_A, 0x50, subAddress, 128, false);
            assertStatus(readStandard.status(), "i2cRead");
            if (!Arrays.equals(writePayload, readStandard.value())) {
                throw new IllegalStateException("Write/read verification failed.");
            }
            printPayload("Standard payload:", readStandard.value());

            var scan = sdk.i2cScanBus(I2cBus.I2C_BUS_A, true);
            assertStatus(scan.status(), "i2cScanBus", ResultCodes.SUCCESS, ResultCodes.FW_I2C_BUS_WITH_NO_TARGETS_CONNECTED);
            if (scan.value() != null) {
                System.out.println("7-bit Address devices:");
                for (int address : scan.value().addresses7Bit()) {
                    System.out.println("\t0x" + String.format("%02X", address));
                }
                System.out.println("10-bit Address devices:");
                for (int address : scan.value().addresses10Bit()) {
                    System.out.println("\t0x" + String.format("%04X", address));
                }
            }
        }
    }
}
