import Web3 from 'web3';
import ERC20ABI from './ERC-20ABI';
import detectEthereumProvider from '@metamask/detect-provider';
import {ElLoading, ElMessage} from "element-plus";

var provider: any;

/**
 * MetaMask插件如果存在，会往window注入一个虚假的web3对象，内部使用都通过调用该脚本
 * window.web3 Metamask插件的web3对象
 * window._web3 内部使用的web3对象（真正的web3）
 */
export const web3 = new Web3();
if (typeof window['ethereum'] !== 'undefined') {
  web3.eth.defaultAccount = window['ethereum']['selectedAddress'];
}
/** 暴露在外部方便调试 */
window['_web3'] = web3;

export async function initWeb3() {
  provider = await detectEthereumProvider();

  if (!provider) {
    ElMessage.warning('请安装MetaMask');
    return false;
  }

  const loading = ElLoading.service({
    lock: true,
    text: '请打开MetaMask完成授权...',
    background: 'rgba(0, 0, 0, 0.7)',
  });

  try {
    web3.setProvider(provider);
    const accounts = await provider.request({
      method: 'eth_requestAccounts',
    });
    //如果用户同意了登录请求，你就可以拿到用户的账号
    web3.eth.defaultAccount = accounts[0];
    loading.close();
    return true;
  } catch (reason) {
    switch (reason) {
      case 'Already processing eth_requestAccounts. Please wait.':  // 已有请求存在
        ElMessage.warning('请打开MetaMask完成授权');
        break;
      case 'User rejected provider access':   //如果用户拒绝了登录请求
        ElMessage.warning('请同意登录请求');
        break;
      default:  // 本不该执行到这里，但是真到这里了，说明发生了意外
        ElMessage.error('登录出错！err:' + reason);
        break;
    }
  }
  loading.close();
  return false;
}

export async function web3Sign(raw: any) {
  const loading = ElLoading.service({
    lock: true,
    text: '请在MetaMask内完成签名...',
    background: 'rgba(0, 0, 0, 0.7)',
  });

  try {
    var {result} = await provider.send('personal_sign', [raw, web3.eth.defaultAccount!.toLowerCase()]);
    loading.close();
    return result;
  } catch (e) {
    console.log(e);
    loading.close();
  }
}

/**
 * 代币相关
 */

export const tokenWeb3 = new Web3();

export function setTokenWeb3Rpc(rpcUrl: any) {
  tokenWeb3.setProvider(new Web3.providers.HttpProvider(rpcUrl));
}

export async function getWeb3Balance(account: any) {
  return tokenWeb3.utils.fromWei(await tokenWeb3.eth.getBalance(account));
}

export async function getWeb3TokenBalance(tokenAddress: any, account: any) {
  const token = new tokenWeb3.eth.Contract(ERC20ABI as any, tokenAddress);
  return await token.methods.balanceOf(account).call();
}

export async function getWeb3TokenInfo(tokenAddress: any) {
  const token = new tokenWeb3.eth.Contract(ERC20ABI as any, tokenAddress);
  const [symbol, decimals] = await Promise.all([
    token.methods.symbol().call(),
    token.methods.decimals().call(),
  ]);
  return {
    symbol,
    decimals,
  };
}
