#include "shared_context.h"
#include "apdu_constants.h"
#include "public_keys.h"
#include "common_ui.h"
#include "os_io_seproxyhal.h"
#include "network.h"
#include "manage_asset_info.h"
#ifdef HAVE_LEDGER_PKI
#include "os_pki.h"
#endif

void handleProvideErc20TokenInformation(uint8_t p1,
                                        uint8_t p2,
                                        const uint8_t *workBuffer,
                                        uint8_t dataLength,
                                        unsigned int *flags,
                                        unsigned int *tx) {
    UNUSED(p1);
    UNUSED(p2);
    UNUSED(flags);
    UNUSED(tx);
    uint32_t offset = 0;
    uint8_t tickerLength;
    uint64_t chain_id;
    uint8_t hash[INT256_LENGTH];
    tokenDefinition_t *token = &get_current_asset_info()->token;
    cx_err_t error = CX_INTERNAL_ERROR;

    PRINTF("Provisioning currentAssetIndex %d\n", tmpCtx.transactionContext.currentAssetIndex);

    if (dataLength < 1) {
        THROW(APDU_RESPONSE_INVALID_DATA);
    }
    tickerLength = workBuffer[offset++];
    dataLength--;
    if ((tickerLength + 1) > sizeof(token->ticker)) {
        THROW(APDU_RESPONSE_INVALID_DATA);
    }
    if (dataLength < tickerLength + 20 + 4 + 4) {
        THROW(APDU_RESPONSE_INVALID_DATA);
    }
    cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
    memmove(token->ticker, workBuffer + offset, tickerLength);
    token->ticker[tickerLength] = '\0';
    offset += tickerLength;
    dataLength -= tickerLength;
    memmove(token->address, workBuffer + offset, 20);
    offset += 20;
    dataLength -= 20;
    // TODO: 4 bytes for this is overkill
    token->decimals = U4BE(workBuffer, offset);
    offset += 4;
    dataLength -= 4;
    // TODO: Handle 64-bit long chain IDs
    chain_id = U4BE(workBuffer, offset);
    if (!app_compatible_with_chain_id(&chain_id)) {
        UNSUPPORTED_CHAIN_ID_MSG(chain_id);
        THROW(APDU_RESPONSE_INVALID_DATA);
    }
    offset += 4;
    dataLength -= 4;

    error = check_signature_with_pubkey("ERC20 Token Info",
                                        hash,
                                        sizeof(hash),
                                        LEDGER_SIGNATURE_PUBLIC_KEY,
                                        sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
#ifdef HAVE_LEDGER_PKI
                                        CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
#endif
                                        (uint8_t *) (workBuffer + offset),
                                        dataLength);
#ifndef HAVE_BYPASS_SIGNATURES
    if (error != CX_OK) {
        THROW(APDU_RESPONSE_INVALID_DATA);
    }
#endif

    G_io_apdu_buffer[0] = tmpCtx.transactionContext.currentAssetIndex;
    validate_current_asset_info();
    U2BE_ENCODE(G_io_apdu_buffer, 1, APDU_RESPONSE_OK);
    io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 3);
}
