import Web3 from 'web3';


export function checkEnvironment() {
    return typeof window !== 'undefined' && typeof window.ethereum !== 'undefined';
}

export async function init() {
    if (!checkEnvironment()) {
        return;
    }
    try {
        let ethereum = window.ethereum
        ethereum.autoRefreshOnNetworkChange = false;
        const accounts = await ethereum.enable();
        let provider = window['ethereum'] || window.web3.currentProvider
        window.web3 = new Web3(provider)
        window.defaultAccount = accounts[0];
        return { address: window.defaultAccount };
    } catch (err) {
        console.log('---err', err);
        return '';
    }
}


export function handleNetworkChanged(callBack){
    window.ethereum.on('networkChanged', function (networkIDstring) {
            callBack && callBack();
        })
}


export function handleAccountsChanged(callBack){
    window.ethereum.on('accountsChanged', function (accounts) {
        callBack && callBack();
      })
}


export async function getAddress() { // 可以直接用 window.defaultAccount
    if (!checkEnvironment()) {
        throw new Error('MetaMask is not installed in the current browser')
    }
    const accounts = await window.web3.eth.getAccounts();
    const myAccount = accounts[0] || '';
    return myAccount;
}


export async function getChainId(){
    const chainId = await ethereum.request({ method: 'eth_chainId' });
    return window.web3.utils.hexToNumber(chainId);
}


export async function getBalance(address = window.defaultAccount) {
    const balance = await window.web3.eth.getBalance(address);
    return balance.toString();

}

export async function getNonce(address = window.defaultAccount) {
    const nonce = await window.web3.eth.getTransactionCount(address);
    return nonce.toString();
}

export async function getBlockNumber() {
    const blockNumber = await window.web3.eth.getBlockNumber();
    return blockNumber.toString();
}

export async function checkTransaction(hash) {
    let result = await window.web3.eth.getTransactionReceipt(hash);
    return result;
}

export async function getBlock(blockHeight) {
    return window.web3.eth.getBlock(blockHeight)
}

export async function sendTransaction({ from = window.defaultAccount, to, value }) {
    if (!to) {
        throw new Error('Please input toAddress for transaction');
    }
    if (!value) {
        throw new Error('Please input the amount of the transaction');
    }
    let result = await window.web3.eth.sendTransaction({ from, to, value })
    return result;
}


export function deployContract({ bytecode, abi, params = [],from = window.defaultAccount, gas = '30000000' }) {
    return new Promise((resolve, reject) => {
        let myContract = new window.web3.eth.Contract(abi);
        let transactionHash;
        var proof = myContract.deploy({
            data: bytecode,
            arguments: params,
        }).send({ from, gas }, function (e, contract) {
            if (e) {
                console.log('----e', e)
            }
            if (contract) {
                console.log('----contract', contract)
            }
        }).on('error', function (error) {
            reject(error)
        }).on('transactionHash', function (hash) {
            console.log('---transactionHash', hash)
            transactionHash = hash;
        }).on('receipt', function (receipt) {
            let contractAddress = receipt.contractAddress.toLowerCase();
            console.log('---receipt', contractAddress) // contains the new contract address
            resolve({transactionHash, contractAddress})
        }).on('confirmation', function (confirmationNumber, receipt) {

        }).then(function (newContractInstance) {
            console.log(newContractInstance.options.address) // instance with the new contract address
        });
    })

}


export function getMyContract({ abi, contractAddress }) {
    return new window.web3.eth.Contract(abi, contractAddress);
}

//type  call send
export function callContract({abi, contractAddress, type = 'send', methodName, params = [], overrides}){
    return new Promise((resolve, reject) => {
        const myContract = new window.web3.eth.Contract(abi, contractAddress);
        let _overrides = {
            // gasLimit: 6000000,
            from: window.defaultAccount, 
            // gasLimit: 1000000,
            value: '0x0'
        }
        if(type == 'send'){
            myContract.methods[methodName](...params).send(overrides || _overrides)
            .on('transactionHash', function (transactionHash) {
                console.log('transactionHash', transactionHash)
            })
            .on('confirmation', function (confirmationNumber, receipt) {
                console.log('confirmation', { confirmationNumber: confirmationNumber, receipt: receipt })
            })
            .on('receipt', function (receipt) {
                console.log('---receipt', receipt)
                resolve(receipt);
            })
            .on('error', function (error, receipt) {
                console.log('---error', error);
                reject(error)
            });
        }else{
            myContract.methods[methodName](...params).call(overrides || _overrides)
            .then((res) => {
                console.log(`---call${methodName}`,res);
                resolve(res)
            }).catch((err) => {
                reject(`Error when calling contract method:${err}`)
            })
        }
        
      })
}


export function getPendingTransactions() {
    window.web3.eth.getPendingTransactions().then((res) => {
        console.log('-----getPendingTransactions', res)
    })
}


export async function signMessage(message) {
    return window.web3.eth.sign(message, window.defaultAccount,)
}


export async function signPersonalMessage(message) {
    return window.web3.eth.personal.sign(message, window.defaultAccount,)
}



export async function verifySignatureRPL(message, sig) {
    return window.web3.eth.accounts.recover(message, sig);
}

export async function verifySignatureVRS(message, sig) {
    let r = sig.slice(0, 66)
    let s = '0x' + sig.slice(66, 130)
    let v = '0x' + sig.slice(130, 132)

    return window.web3.eth.accounts.recover(message, v, r, s);
}

export function recoverTransaction(sig){
    return window.web3.eth.accounts.recoverTransaction(sig);
}


export function decodeLog(inputs, hexString, topics){
    return window.web3.eth.abi.decodeLog(inputs, hexString, topics);
}





