package com.binho.cosmicsdk.examples.i3c.ccc;

import com.binho.cosmicsdk.CosmicSdk;
import com.binho.cosmicsdk.ResultCodes;
import com.binho.cosmicsdk.Types.I2cTransferRate;
import com.binho.cosmicsdk.Types.I3cDriveStrength;
import com.binho.cosmicsdk.Types.I3cEvent;
import com.binho.cosmicsdk.Types.I3cOpenDrainTransferRate;
import com.binho.cosmicsdk.Types.I3cPushPullRate;
import com.binho.cosmicsdk.Types.I3cTargetResetDefByte;
import com.binho.cosmicsdk.Types.I3cTransferDirection;

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

public final class I3cCccExample {
    private I3cCccExample() {
    }

    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.i3cSetBusVoltage(3300), "i3cSetBusVoltage");
            assertStatus(
                    sdk.i3cControllerInit(
                            I3cPushPullRate.PUSH_PULL_10_MHz_DC_40,
                            I3cOpenDrainTransferRate.OPEN_DRAIN_400_KHz,
                            I2cTransferRate.FAST_MODE,
                            I3cDriveStrength.FAST
                    ),
                    "i3cControllerInit",
                    ResultCodes.SUCCESS,
                    ResultCodes.FW_INTERFACE_ALREADY_INITIALIZED
            );
            assertStatus(sdk.i3cInitBus(), "i3cInitBus");

            var pid = sdk.i3cCccGetpid(0x09);
            assertStatus(pid.status(), "i3cCccGetpid");
            printHexPayload("PID:", pid.value());

            var bcr = sdk.i3cCccGetbcr(0x09);
            assertStatus(bcr.status(), "i3cCccGetbcr");
            System.out.println("BCR: " + bcr.value());

            var dcr = sdk.i3cCccGetdcr(0x09);
            assertStatus(dcr.status(), "i3cCccGetdcr");
            System.out.println("DCR: " + dcr.value());

            var caps = sdk.i3cCccGetcaps(0x08);
            assertStatus(caps.status(), "i3cCccGetcaps");
            printHexPayload("CAPS:", caps.value());

            var mrl = sdk.i3cCccGetmrl(0x09);
            assertStatus(mrl.status(), "i3cCccGetmrl(0x09)");
            System.out.println("MRL 0x09: " + mrl.value().maxReadLength() + ", IBI length: " + mrl.value().ibiLength());

            assertStatus(sdk.i3cCccSetmrlBroadcast(0x0F03, 0x03), "i3cCccSetmrlBroadcast");
            assertStatus(sdk.i3cCccSetmrlDirect(0x09, 0x0200, null), "i3cCccSetmrlDirect");

            var mwl = sdk.i3cCccGetmwl(0x09);
            assertStatus(mwl.status(), "i3cCccGetmwl");
            System.out.println("MWL 0x09: " + mwl.value());

            assertStatus(sdk.i3cCccSetmwlBroadcast(0x0F03), "i3cCccSetmwlBroadcast");
            assertStatus(sdk.i3cCccSetmwlDirect(0x08, 0x0200), "i3cCccSetmwlDirect");

            assertStatus(sdk.i3cCccDisecBroadcast(I3cEvent.IBI | I3cEvent.CR | I3cEvent.HJ), "i3cCccDisecBroadcast");
            assertStatus(sdk.i3cCccDisecDirect(0x09, I3cEvent.CR | I3cEvent.HJ), "i3cCccDisecDirect");
            assertStatus(sdk.i3cCccEnecBroadcast(I3cEvent.IBI | I3cEvent.CR | I3cEvent.HJ), "i3cCccEnecBroadcast");
            assertStatus(sdk.i3cCccEnecDirect(0x09, I3cEvent.CR | I3cEvent.HJ), "i3cCccEnecDirect");

            var rstRead = sdk.i3cCccRstactDirect(0x08, I3cTargetResetDefByte.NO_RESET, I3cTransferDirection.READ);
            assertStatus(rstRead.status(), "i3cCccRstactDirect(read)");
            System.out.println("RSTACT read value: " + rstRead.value());

            assertStatus(sdk.i3cCccRstactBroadcast(I3cTargetResetDefByte.NO_RESET), "i3cCccRstactBroadcast");
            assertStatus(sdk.i3cCccRstactDirect(0x09, I3cTargetResetDefByte.RESET_WHOLE_TARGET, I3cTransferDirection.WRITE).status(), "i3cCccRstactDirect(write)");
            assertStatus(sdk.i3cTargetResetPattern(), "i3cTargetResetPattern");
            assertStatus(sdk.i3cHdrExitPattern(), "i3cHdrExitPattern");
        }
    }
}
