package io.synor.contract;

import com.google.gson.annotations.SerializedName;
import java.util.List;
import java.util.Map;

/**
 * Contract SDK type definitions.
 */
public class ContractTypes {

    // ==================== ABI Types ====================

    public static class AbiParameter {
        @SerializedName("name")
        public String name;

        @SerializedName("type")
        public String type;

        @SerializedName("indexed")
        public Boolean indexed;

        @SerializedName("components")
        public List<AbiParameter> components;
    }

    public static class AbiEntry {
        @SerializedName("type")
        public String type;

        @SerializedName("name")
        public String name;

        @SerializedName("inputs")
        public List<AbiParameter> inputs;

        @SerializedName("outputs")
        public List<AbiParameter> outputs;

        @SerializedName("stateMutability")
        public String stateMutability;

        @SerializedName("anonymous")
        public Boolean anonymous;
    }

    // ==================== Deployment ====================

    public static class DeployContractOptions {
        public String bytecode;
        public List<AbiEntry> abi;
        public Object[] constructorArgs;
        public String value;
        public Long gasLimit;
        public String gasPrice;
        public Long nonce;
    }

    public static class DeploymentResult {
        @SerializedName("contract_address")
        public String contractAddress;

        @SerializedName("transaction_hash")
        public String transactionHash;

        @SerializedName("deployer")
        public String deployer;

        @SerializedName("gas_used")
        public Long gasUsed;

        @SerializedName("block_number")
        public Long blockNumber;

        @SerializedName("block_hash")
        public String blockHash;
    }

    // ==================== Contract Interaction ====================

    public static class CallContractOptions {
        public String contract;
        public String method;
        public Object[] args;
        public List<AbiEntry> abi;
    }

    public static class SendContractOptions {
        public String contract;
        public String method;
        public Object[] args;
        public List<AbiEntry> abi;
        public String value;
        public Long gasLimit;
        public String gasPrice;
        public Long nonce;
    }

    public static class TransactionResult {
        @SerializedName("transaction_hash")
        public String transactionHash;

        @SerializedName("block_number")
        public Long blockNumber;

        @SerializedName("block_hash")
        public String blockHash;

        @SerializedName("gas_used")
        public Long gasUsed;

        @SerializedName("effective_gas_price")
        public String effectiveGasPrice;

        @SerializedName("status")
        public String status;

        @SerializedName("logs")
        public List<EventLog> logs;
    }

    // ==================== Events ====================

    public static class EventLog {
        @SerializedName("address")
        public String address;

        @SerializedName("topics")
        public List<String> topics;

        @SerializedName("data")
        public String data;

        @SerializedName("block_number")
        public Long blockNumber;

        @SerializedName("transaction_hash")
        public String transactionHash;

        @SerializedName("log_index")
        public Integer logIndex;

        @SerializedName("block_hash")
        public String blockHash;

        @SerializedName("removed")
        public Boolean removed;
    }

    public static class DecodedEvent {
        @SerializedName("name")
        public String name;

        @SerializedName("signature")
        public String signature;

        @SerializedName("args")
        public Map<String, Object> args;

        @SerializedName("log")
        public EventLog log;
    }

    public static class EventFilter {
        public String contract;
        public String event;
        public Long fromBlock;
        public Long toBlock;
        public List<String> topics;
        public List<AbiEntry> abi;
    }

    // ==================== ABI Utilities ====================

    public static class EncodeCallOptions {
        public String method;
        public Object[] args;
        public List<AbiEntry> abi;
    }

    public static class DecodeResultOptions {
        public String data;
        public String method;
        public List<AbiEntry> abi;
    }

    // ==================== Gas Estimation ====================

    public static class EstimateGasOptions {
        public String contract;
        public String method;
        public Object[] args;
        public List<AbiEntry> abi;
        public String value;
    }

    public static class GasEstimation {
        @SerializedName("gas_limit")
        public Long gasLimit;

        @SerializedName("gas_price")
        public String gasPrice;

        @SerializedName("max_fee_per_gas")
        public String maxFeePerGas;

        @SerializedName("max_priority_fee_per_gas")
        public String maxPriorityFeePerGas;

        @SerializedName("estimated_cost")
        public String estimatedCost;
    }

    // ==================== Contract Information ====================

    public static class BytecodeInfo {
        @SerializedName("bytecode")
        public String bytecode;

        @SerializedName("deployed_bytecode")
        public String deployedBytecode;

        @SerializedName("size")
        public Integer size;

        @SerializedName("is_contract")
        public Boolean isContract;
    }

    public static class VerifyContractOptions {
        public String address;
        public String sourceCode;
        public String compilerVersion;
        public String constructorArgs;
        public Boolean optimization;
        public Integer optimizationRuns;
        public String license;
    }

    public static class VerificationResult {
        @SerializedName("verified")
        public Boolean verified;

        @SerializedName("address")
        public String address;

        @SerializedName("compiler_version")
        public String compilerVersion;

        @SerializedName("optimization")
        public Boolean optimization;

        @SerializedName("optimization_runs")
        public Integer optimizationRuns;

        @SerializedName("license")
        public String license;

        @SerializedName("abi")
        public List<AbiEntry> abi;

        @SerializedName("source_code")
        public String sourceCode;
    }

    // ==================== Multicall ====================

    public static class MulticallRequest {
        public String contract;
        public String method;
        public Object[] args;
        public List<AbiEntry> abi;
    }

    public static class MulticallResult {
        @SerializedName("success")
        public Boolean success;

        @SerializedName("result")
        public Object result;

        @SerializedName("error")
        public String error;
    }

    // ==================== Storage ====================

    public static class ReadStorageOptions {
        public String contract;
        public String slot;
        public Long blockNumber;
    }
}
