import { getDcomm, createTests, Matcher } from "./e2etestlib"
import { KeystoreAPI } from "src/apis/keystore/api"
import BN from "bn.js"

describe("ASTChain", (): void => {
  let tx = { value: "" }
  let asset = { value: "" }
  let addrB = { value: "" }
  let addrC = { value: "" }

  const dcomm = getDcomm()
  const astchain = dcomm.ASTChain()
  const keystore = new KeystoreAPI(dcomm)

  const user: string = "dcommJsASTChainUser"
  const passwd: string = "dcommJsP1ssw4rd"
  const badUser: string = "asdfasdfsa"
  const badPass: string = "pass"
  const memo: string = "hello world"
  const whaleAddr: string = "AST-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p"
  const key: string =
    "PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN"

  // test_name        response_promise                            resp_fn          matcher           expected_value/obtained_value
  const tests_spec: any = [
    [
      "createUser",
      () => keystore.createUser(user, passwd),
      (x) => x,
      Matcher.toEqual,
      () => { return {} }
    ],
    [
      "createaddrB",
      () => astchain.createAddress(user, passwd),
      (x) => x,
      Matcher.Get,
      () => addrB
    ],
    [
      "createaddrB",
      () => astchain.createAddress(user, passwd),
      (x) => x,
      Matcher.Get,
      () => addrC
    ],
    [
      "incorrectUser",
      () =>
        astchain.send(
          badUser,
          passwd,
          "DCM",
          10,
          addrB.value,
          [addrC.value],
          addrB.value,
          memo
        ),
      (x) => x,
      Matcher.toThrow,
      () => `problem retrieving user "${badUser}": incorrect password for user "${badUser}"`
    ],
    [
      "incorrectPass",
      () =>
        astchain.send(
          user,
          badPass,
          "DCM",
          10,
          addrB.value,
          [addrC.value],
          addrB.value,
          memo
        ),
      (x) => x,
      Matcher.toThrow,
      () => `problem retrieving user "${user}": incorrect password for user "${user}"`
    ],
    [
      "getBalance",
      () => astchain.getBalance(whaleAddr, "DCM"),
      (x) => x.balance,
      Matcher.toBe,
      () => "300000000000000000"
    ],
    [
      "getBalance2",
      () => astchain.getBalance(whaleAddr, "DCM"),
      (x) => x.utxoIDs[0].txID,
      Matcher.toBe,
      () => "BUuypiq2wyuLMvyhzFXcPyxPMCgSp7eeDohhQRqTChoBjKziC"
    ],
    [
      "importKey",
      () => astchain.importKey(user, passwd, key),
      (x) => x,
      Matcher.toBe,
      () => whaleAddr
    ],
    [
      "send",
      () =>
        astchain.send(
          user,
          passwd,
          "DCM",
          10,
          addrB.value,
          [whaleAddr],
          whaleAddr,
          memo
        ),
      (x) => x.txID,
      Matcher.Get,
      () => tx
    ],
    [
      "sendMultiple",
      () =>
        astchain.sendMultiple(
          user,
          passwd,
          [
            { assetID: "DCM", amount: 10, to: addrB.value },
            { assetID: "DCM", amount: 20, to: addrC.value }
          ],
          [whaleAddr],
          whaleAddr,
          memo
        ),
      (x) => x.txID,
      Matcher.Get,
      () => tx
    ],
    [
      "listAddrs",
      () => astchain.listAddresses(user, passwd),
      (x) => x.sort(),
      Matcher.toEqual,
      () => [whaleAddr, addrB.value, addrC.value].sort()
    ],
    [
      "exportKey",
      () => astchain.exportKey(user, passwd, addrB.value),
      (x) => x,
      Matcher.toMatch,
      () => /PrivateKey-\w*/
    ],
    [
      "export",
      () =>
        astchain.export(
          user,
          passwd,
          "ACT" + addrB.value.substring(1),
          new BN(10),
          "DCM"
        ),
      (x) => x,
      Matcher.toThrow,
      () => "couldn't unmarshal an argument"
    ],
    [
      "import",
      () => astchain.import(user, passwd, addrB.value, "ATH"),
      (x) => x,
      Matcher.toThrow,
      () => "problem issuing transaction: no import inputs"
    ],
    [
      "createFixed",
      () =>
        astchain.createFixedCapAsset(user, passwd, "Some Coin", "SCC", 0, [
          { address: whaleAddr, amount: "10000" }
        ]),
      (x) => x,
      Matcher.Get,
      () => asset
    ],
    [
      "createVar",
      () =>
        astchain.createVariableCapAsset(user, passwd, "Some Coin", "SCC", 0, [
          { minters: [whaleAddr], threshold: 1 }
        ]),
      (x) => x,
      Matcher.Get,
      () => asset
    ],
    [
      "mint",
      () =>
        astchain.mint(user, passwd, 1500, asset.value, addrB.value, [whaleAddr]),
      (x) => x,
      Matcher.toThrow,
      () => "couldn't unmarshal an argument"
    ],
    [
      "getTx",
      () => astchain.getTx(tx.value),
      (x) => x,
      Matcher.toMatch,
      () => /\w+/
    ],
    [
      "getTxStatus",
      () => astchain.getTxStatus(tx.value),
      (x) => x,
      Matcher.toBe,
      () => "Processing"
    ],
    [
      "getAssetDesc",
      () => astchain.getAssetDescription(asset.value),
      (x) => [x.name, x.symbol],
      Matcher.toEqual,
      () => ["Some Coin", "SCC"]
    ]
  ]

  createTests(tests_spec)
})