import { TransactionInfo } from "types";
import fetch from "cross-fetch";
import { HttpProviderOptions, JsonRpcPayload, JsonRpcResponse } from 'web3-core-helpers';

export class SentioProvider {
  transactionInfo: TransactionInfo;
  chainId: string;
  host: string;

  constructor(host: string, options?: HttpProviderOptions) {
    this.host = host;
  }

  async init(txnHash: string, chainId: string) {
    this.chainId = chainId;
    const url = new URL("solidity/transaction_info", this.host)
    url.searchParams.append("txHash", txnHash)
    const resp = await fetch(url);
    this.transactionInfo = await resp.json();
  }

  send(payload: JsonRpcPayload, callback: (error: Error | null, result?: JsonRpcResponse | undefined) => void): void {
    let response: JsonRpcResponse = {
      id: payload.id!,
      jsonrpc: payload.jsonrpc,
    }
    switch (payload.method) {
      case "debug_traceTransaction":
        response.result = this.transactionInfo.trace;
        break;
      case "eth_getTransactionByHash":
        response.result = this.transactionInfo.transaction;
        break;
      case "eth_getTransactionReceipt":
        response.result = this.transactionInfo.transactionReceipt;
        break;
      case "eth_getBlockByNumber":
        response.result = this.transactionInfo.block;
        break;
      case "eth_chainId":
        response.result = this.chainId;
        break;
      case "eth_getCode":
        if (payload.params != null) {
          const contract = payload.params[0];
          const matchedKey = Object.keys(this.transactionInfo.code).find(c => c.toLowerCase() === contract);
          if (matchedKey) {
            response.result = this.transactionInfo.code[matchedKey];
            break;
          }
        }
        callback(new Error("Get code request param is null or matched key is null."));
        return;
      case "debug_storageRangeAt":
        try {
          const url = new URL("solidity/storage_info", this.host);
          url.searchParams.append("blockHash", payload.params![0]);
          url.searchParams.append("txIdx", payload.params![1]);
          url.searchParams.append("contractAddress", payload.params![2]);
          url.searchParams.append("keyStart", payload.params![3]);
          url.searchParams.append("maxResult", payload.params![4]);
          fetch(url).then(resp => resp.json().then(result => callback(null, result))).catch(r => callback(new Error(r), undefined));
        } catch (e) {
          callback(e, undefined);
          return;
        }
        break;
      default:
        callback(new Error(`${payload.method} is not supported.`), undefined);
        return;
    }
    callback(null, response);
  }

  supportsSubscriptions(): boolean {
    return false;
  }

  disconnect() { }
}
