const { HDPrivateKey, PrivateKey } = require('bitcore-lib')
const { TemplateWarehouse, Compiler } = require('@asimovdev/asimovjs')
const readlineSync = require('readline-sync')
const colors = require('colors')
const storage = require('./storage')
const { rpc } = require('./rpc')
const path = require('path');
let Module = require('../lib/flow_4.0.0')
let compiler = new Compiler(Module)
let warehouse = new TemplateWarehouse({
  baseProvider: {
    chainRpcProvider: rpc
  }
})



module.exports = {
  createTemplate: function(source, name, category, gasLimit, privateKey) {

    return new Promise((resolve, reject) => {
      if (!source) {
        console.log(colors.yellow('.sol source file is not specified!'))
        return
      }

      if (!name) {
        console.log(colors.yellow('template name is not specified!'))
        return
      }

      if (category == undefined) {
        console.log(colors.yellow('template category is not specified!'))
        return
      }
      if (!privateKey) {
        console.log(colors.yellow('private key is not specified!'))
        return
      }
      if (!gasLimit) {
        console.log(colors.yellow('gas limit is not specified!'))
        return
      }

      let accounts = storage.getAccount()
      let addresses = [];
      accounts.forEach(a => {
        addresses.push(a.address)
      })


      compiler.compileSol(source).then(res => {
        let { contracts, source } = res
        console.log(colors.green('source file compiles successfully, please choose one template to upload:'))
        let keys = []

        for (let key in contracts) {
          keys.push(key)
        }
        let index = readlineSync.keyInSelect(keys, 'which contract template to upload?')
        let contractName = keys[index]
        console.log(colors.green('uploading template ' + contractName))
        let contract = contracts[contractName]
        let byteCode = contract.evm.bytecode.object
        let abi = contract.abi

        warehouse.create({
          category: category,
          name: name,
          bytecode: byteCode,
          abi: JSON.stringify(abi),
          source: source,
          gasLimit: gasLimit,
          privateKey: privateKey
        }).then(res => {
          console.log(res)
          resolve(res)
        }).catch(e => {
          console.log(e)
          reject(e)
        })
      })
    })


  },
  listTemplate: function(category) {
    // let warehouse = new TemplateWarehouse({
    //   baseProvider: {
    //     chainRpcProvider: rpc
    //   }
    // })
    if (category == undefined) {
      console.log(colors.yellow('template category is not specified!'))
      return
    }
    let ca = Number(category)
    // let accounts = storage.getAccount()
    // accounts.forEach(a => {
    //   console.log(colors.green(a.address))
    // })
    if (ca == NaN) {
      console.log(colors.yellow('template category should be a number!'))
      return
    }
    rpc.getContractTemplateList(ca).then(res => {
      res.forEach((t, index) => {
        let date = new Date(t.createTime * 1000)
        console.log(colors.green((index + 1) + '. ' + t.name + '  ' + t.key + ' ' + date.getFullYear() + ' ' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes()))
      })
    })
  },

  deployTemplate: function(id, args, gasLimit, privateKey) {
    // let warehouse = new TemplateWarehouse({
    //   baseProvider: {
    //     chainRpcProvider: rpc
    //   }
    //

    let arguments = (args && JSON.parse(args)) || []

    warehouse.deploy({
      templateId: id,
      args: arguments || [],
      gasLimit: gasLimit,
      privateKey: privateKey
    }).then(res => {
      console.log(colors.green('success!'))
      console.log(colors.green('contract address: ' + res[0]))
    }).catch(e => {
      console.log(colors.red(e))
    })

  },
  createAndDeployTemplate(source, name, category, gasLimit, privateKey, args) {

    let count = 0
    let queryCount = 10
    let queryLoop = (txId, resolve, reject) => {
      rpc.getTransactionReceipt(txId).then(res => {
        if (!res) {
          count++
          if (count >= queryCount) {
            reject(0)
          }
          setTimeout(() => {
            queryLoop(txId, resolve, reject)
          }, 5000)
        } else if (res.status == 1) {
          resolve(1)
        } else {
          reject(0)
        }
      })
    }

    this.createTemplate(source, name, category, gasLimit, privateKey).then(res => {

      let txId = res;
      let promise = new Promise((resolve, reject) => {

        queryLoop(txId, resolve, reject)

      })
      promise.then(res => {

        this.deployTemplate(txId, args, gasLimit, privateKey)

      }).catch(e => {
        console.log(colors.red(e))
      })

    }).catch(e => {
      console.log(colors.red(e))
    })
  }
}
