#!/usr/bin/env node
const { init, callContract, ether, getTxHash } = require('./ThkContract.js');
const Web3 = require('web3');
const fs = require('fs');
const inquirer = require('inquirer');
const colors = require('colors');
const config = JSON.parse(fs.readFileSync("./config.json"));

let contractInstance;
let choiceList = [];

module.exports = (contractAbi) => {
  inquirer.prompt([
    {
      type: 'input',
      name: 'mnemonic',
      message: "输入助记词",
      default: function () {
        return config.mnemonic;
      }
    }, {
      type: 'input',
      name: 'contractAddress',
      message: "输入合约地址",
      validate: function (value) {
        if (Web3.utils.isAddress(value)) {
          return true;
        }
        return '地址输入不正确';
      },
      default: function () {
        return config.contractAddress;
      }
    }
  ])
    .then(answers => {
      fs.writeFile('./config.json', JSON.stringify(answers, null, "\t"), function (err) {
        if (err) { console.log(err) }
        open(contractAbi, answers.contractAddress)
      })
    });
}


const open = (contractAbi, contractAddress) => {
  init().then(async () => {
    contractInstance = await callContract(contractAbi, contractAddress);
    choiceList = formatChoice(contractAbi);
    choice();
  })
}

const formatChoice = (contractAbi) => {
  let _choiceList = [];
  for (let i = 0; i < contractAbi.length; i++) {
    if (contractAbi[i].type == 'function') {
      let params = '';
      if (typeof contractAbi[i].inputs != 'undefined') {
        if (contractAbi[i].inputs.length > 0) {
          for (let j = 0; j < contractAbi[i].inputs.length; j++) {
            if (j > 0) params = params + ', ';
            params = params + contractAbi[i].inputs[j].type + ' ' + contractAbi[i].inputs[j].name;
          }
        }
      }
      let name = contractAbi[i].desc;
      let obj = {
        name: name,
        value: _choiceList.length,
        function: contractAbi[i].name,
        type: contractAbi[i].stateMutability,
        inputs: typeof contractAbi[i].inputs == 'undefined' ? [] : contractAbi[i].inputs
      };
      _choiceList.push(obj);
    }
  }
  return _choiceList;
}

const choice = () => {
  console.log("");
  inquirer.prompt([
    {
      type: 'list',
      name: 'function',
      message: "选择方法:",
      choices: choiceList
    }
  ])
    .then(answers => {
      answer(choiceList[answers.function])
    });
}

const answer = (answers) => {
  console.log("");
  let params = '';
  if (answers.inputs.length > 0) {
    for (let j = 0; j < answers.inputs.length; j++) {
      if (j > 0) params = params + ', ';
      params = params + answers.inputs[j].type + ' ' + answers.inputs[j].name;
    }
  }

  call(answers.function, answers.inputs, answers.type);

}

const call = (functionName, inputs, type) => {
  if (inputs.length > 0) {
    let questions = [];
    for (let i = 0; i < inputs.length; i++) {
      if (inputs[i].type == 'address') {
        questions.push(
          {
            type: 'input',
            name: inputs[i].name == "" ? inputs[i].desc : inputs[i].name,
            message: inputs[i].type + " " + inputs[i].desc + ':',
            validate: function (value) {
              if (Web3.utils.isAddress(value)) {
                return true;
              }
              return '地址输入不正确';
            }
          }
        )
      } else if (inputs[i].type == 'uint256') {
        questions.push(
          {
            type: 'input',
            name: inputs[i].name == "" ? inputs[i].desc : inputs[i].name,
            message: inputs[i].type + " " + inputs[i].desc + ':',
            validate: function (value) {
              var re = /^[0-9]*$/;
              if (re.test(value)) {
                return true;
              }
              return '数额输入不正确';
            }
          }
        );
      } else {
        questions.push(
          {
            type: 'input',
            name: inputs[i].name == "" ? inputs[i].desc : inputs[i].name,
            message: inputs[i].type + " " + inputs[i].desc + ':',
          }
        );
      }
    }
    inquirer.prompt(questions)
      .then(answers => {
        let params = [];
        for (let i = 0; i < inputs.length; i++) {
          params.push(answers[inputs[i].name == "" ? inputs[i].desc : inputs[i].name].toLowerCase());
        }
        let result = contractInstance[functionName](...params);
        txResult(result);
      });
  } else {
    let result = contractInstance[functionName]();
    txResult(result);
  }
}
const txResult = (result) => {
  if (result.TXhash != undefined) {
    console.log(JSON.stringify(result).gray);
    getTxHash(result.TXhash).then((conresp) => {
      if (conresp.status == 1) {
        out = conresp.out != '0x' ? '输出结果:' + conresp.out : 'TX Hash:' + result.TXhash
        console.log('调用成功!'.green, out.yellow)
      } else {
        console.log('调用失败'.red, result.TXhash, conresp)
      }
      choice();
    })
  } else {
    console.log('输出结果:'.green, JSON.stringify(result).yellow);
    choice();
  }
}