"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createOwner = exports.WriteableTitleEscrowOwner = exports.TitleEscrowOwner = exports.EthereumAccountOwner = exports.Owner = exports.isAddressTitleEscrow = void 0;

var _ethers = require("ethers");

var _provider = require("./provider");

var _logger = require("./util/logger");

var _TitleEscrow = require("../build/contracts/TitleEscrow.json");

var _transaction = require("./util/transaction");

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

const _getLogger = (0, _logger.getLogger)("owner"),
      error = _getLogger.error;

const isAddressTitleEscrow =
/*#__PURE__*/
function () {
  var _ref = _asyncToGenerator(function* ({
    address,
    web3Provider = (0, _provider.getWeb3Provider)()
  }) {
    try {
      const MaybeTitleEscrowContract = new _ethers.ethers.Contract(address, JSON.stringify(_TitleEscrow.abi), web3Provider);
      return yield MaybeTitleEscrowContract.supportsInterface("0xad3fae94");
    } catch (e) {
      error(e);
    }

    return false;
  });

  return function isAddressTitleEscrow(_x) {
    return _ref.apply(this, arguments);
  };
}();

exports.isAddressTitleEscrow = isAddressTitleEscrow;

class Owner {
  constructor({
    address
  }) {
    _defineProperty(this, "address", void 0);

    this.address = address;
  }

}

exports.Owner = Owner;

class EthereumAccountOwner extends Owner {
  isTitleEscrow() {
    return false;
  }

}

exports.EthereumAccountOwner = EthereumAccountOwner;

class TitleEscrowOwner extends Owner {
  // This constructor does not check if the target address is a TitleEscrow as we cannot await methods in the constructor
  // Use the createOwner method below if you are not sure if the target is a TitleEscrow contract
  constructor({
    address,
    web3Provider = (0, _provider.getWeb3Provider)()
  }) {
    super({
      address
    });

    _defineProperty(this, "web3Provider", void 0);

    _defineProperty(this, "contractInstance", void 0);

    this.web3Provider = web3Provider;
    this.contractInstance = new _ethers.ethers.Contract(address, JSON.stringify(_TitleEscrow.abi), web3Provider);
  }

  isTitleEscrow() {
    return true;
  }

  beneficiary() {
    var _this = this;

    return _asyncToGenerator(function* () {
      return _this.contractInstance.beneficiary();
    })();
  }

  holder() {
    var _this2 = this;

    return _asyncToGenerator(function* () {
      return _this2.contractInstance.holder();
    })();
  }

  endorsedTransferTarget() {
    var _this3 = this;

    return _asyncToGenerator(function* () {
      return _this3.contractInstance.approvedTransferTarget();
    })();
  }

}

exports.TitleEscrowOwner = TitleEscrowOwner;

class WriteableTitleEscrowOwner extends TitleEscrowOwner {
  constructor({
    address,
    wallet = (0, _provider.getWallet)(),
    web3Provider = (0, _provider.getWeb3Provider)()
  }) {
    super({
      address,
      web3Provider
    });

    _defineProperty(this, "wallet", void 0);

    if (!wallet) {
      throw new Error("WriteableTitleEscrowOwner requires a wallet to be supplied at initialisation");
    }

    this.wallet = wallet;
    this.contractInstance = new _ethers.ethers.Contract(address, JSON.stringify(_TitleEscrow.abi), wallet);
  }

  static deployEscrowContract({
    registryAddress,
    beneficiaryAddress,
    holderAddress,
    wallet = (0, _provider.getWallet)(),
    web3Provider = (0, _provider.getWeb3Provider)()
  }) {
    return _asyncToGenerator(function* () {
      if (!wallet) throw new Error("Deploying contract requires a wallet to be supplied");
      if (!web3Provider) throw new Error("Deploying contract requires the web3 provider");
      if (!registryAddress) throw new Error("Please provide the registry address");
      if (!beneficiaryAddress || !holderAddress) throw new Error("Escrow contract requires beneficiary and holder address");
      const factory = new _ethers.ethers.ContractFactory(JSON.stringify(_TitleEscrow.abi), _TitleEscrow.bytecode, wallet);
      const contract = yield factory.deploy(registryAddress, beneficiaryAddress, holderAddress);
      yield contract.deployed();
      return new TitleEscrowOwner({
        address: contract.address,
        web3Provider
      });
    })();
  }

  changeHolder(newHolder) {
    var _this4 = this;

    return _asyncToGenerator(function* () {
      return (0, _transaction.waitForTransaction)((yield _this4.contractInstance.changeHolder(newHolder)));
    })();
  }

  endorseTransfer(newBeneficiary) {
    var _this5 = this;

    return _asyncToGenerator(function* () {
      return (0, _transaction.waitForTransaction)(_this5.contractInstance.endorseTransfer(newBeneficiary));
    })();
  }

  transferTo(newBeneficiary) {
    var _this6 = this;

    return _asyncToGenerator(function* () {
      return (0, _transaction.waitForTransaction)(_this6.contractInstance.transferTo(newBeneficiary));
    })();
  }

}

exports.WriteableTitleEscrowOwner = WriteableTitleEscrowOwner;

const createOwner =
/*#__PURE__*/
function () {
  var _ref2 = _asyncToGenerator(function* ({
    address,
    web3Provider = (0, _provider.getWeb3Provider)(),
    wallet = (0, _provider.getWallet)()
  }) {
    if (yield isAddressTitleEscrow({
      address,
      web3Provider
    })) {
      if (wallet) {
        return new WriteableTitleEscrowOwner({
          address,
          web3Provider,
          wallet
        });
      }

      return new TitleEscrowOwner({
        address,
        web3Provider
      });
    }

    return new EthereumAccountOwner({
      address
    });
  });

  return function createOwner(_x2) {
    return _ref2.apply(this, arguments);
  };
}();

exports.createOwner = createOwner;