package com.r35157.libs.jupiter.perps.impl.anchoridl;

import com.r35157.libs.solana.SolanaAccountInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.math.BigInteger;
import java.util.Base64;

import static com.r35157.libs.jupiter.perps.impl.anchoridl.DecodingPrimitives.*;

class AnchorIdlJupiterPerpsCustodyDecoder {

    @Nullable JupiterCustodyAccountInfo decode(
            @NotNull ΩJupiterCustodyAccountInfoEncodedΩ encodedCustodyAccountInfo
    ) {
        ΩJupiterPerpsPostionIdlΩ idl = decodeIdl(encodedCustodyAccountInfo);

        JupiterCustodyAccountInfo cai = new JupiterCustodyAccountInfo(
                decodePublicKey(idl, MINT_OFFSET),
                decodeCumulativeInterestRate(idl)
        );

        return cai;
    }

    private ΩJupiterPerpsCustodyAccountIdlΩ decodeIdl(ΩJupiterCustodyAccountInfoEncodedΩ encodedCustodyAccountInfo) {
        ΩJupiterPerpsCustodyAccountIdlΩ idl = base64.decode(encodedCustodyAccountInfo.data());

        if (idl.length < CUMULATIVE_INTEREST_RATE_OFFSET + U128_LENGTH) {
            String errMsg = "Jupiter Perps custody account data is too short: " + idl.length;
            throw new IllegalArgumentException(errMsg);
        }

        return idl;
    }

    private @NotNull ΩJupiterCumulativeInterestRateΩ decodeCumulativeInterestRate(ΩJupiterPerpsCustodyAccountIdlΩ idl) {
        byte[] bytes = readU128(idl, CUMULATIVE_INTEREST_RATE_OFFSET);
        ΩJupiterCumulativeInterestRateΩ cumulativeInterestRate = new ΩJupiterCumulativeInterestRateΩ(1, bytes);

        return cumulativeInterestRate;
    }

    // Offsets:
    //    8  discriminator
    //   +32 pool
    //   +32 mint
    //   +32 token_account
    //   +1  decimals
    //   +1  is_stable
    //   +45 oracle
    //   +48 pricing
    //   +7  permissions
    //   +8  target_ratio_bps
    //   +48 assets

    private static final int DISCRIMINATOR_LENGTH = 8;
    private static final int MINT_OFFSET = DISCRIMINATOR_LENGTH + PUBLIC_KEY_LENGTH;
    private static final int FUNDING_RATE_STATE_OFFSET = 262;
    private static final int CUMULATIVE_INTEREST_RATE_OFFSET = FUNDING_RATE_STATE_OFFSET;

    private static final Base64.Decoder base64 = Base64.getDecoder();
}