
import BigNumber from 'bignumber.js';
import { getLatestABI } from '../../services/AbiService';
import Mutex from '../../utils/MutexChecker';
import { Derivative } from '../Derivative';
import Services from '../../Services';
import { IndexProductStatus, DerivativeProviders, DerivativeStatus } from '../../interfaces/Enums';

export class IndexBuyTokenService extends Services {
  private derivativeFunctions: Derivative;
  private productAddress;
  private minimumETHBalanceToBuy = 1000;

  constructor(productAddress: string) {
    super();
    this.productAddress = productAddress;
    this.derivativeFunctions = new Derivative(productAddress);
  }

  public setMinimumETHBalanceToBuy(_minimumETHBalanceToBuy: number) {
    this.minimumETHBalanceToBuy = _minimumETHBalanceToBuy;
  }

  public getMinimumETHBalanceToBuy() {
    return this.minimumETHBalanceToBuy;
  }

  public async getETHBalance(): Promise<BigNumber> {

    try {
      return await this.derivativeFunctions.nativeContract.getETHBalance.call();
    } catch (e) {
      return await this.rpcService.getBalance(this.productAddress);
    }
  }

  public async canBuyTokens(): Promise<boolean> {
    const mutex = new Mutex(this.productAddress);
    const mutexResult = await mutex.checkMutex(IndexProductStatus.BUYING);
    const lockerResult = await mutex.checkLocker(DerivativeProviders.BUYTOKENS);

    if (!mutexResult.flag || mutexResult.productStatus === IndexProductStatus.AVAILABLE && !lockerResult.flag) {
      return false;
    }

    // If the balance is smaller than MINIMUM_BUYTOKENS wei (0.000000000000001 ETH), we don't do the allocation.
    // This is to prevent any leftover funds from rounding.
    if ((await this.getETHBalance()).toNumber() < this.minimumETHBalanceToBuy) {
      return false;
    }

    if ((await this.derivativeFunctions.getStatus()) === DerivativeStatus.Closed) {
      return false;
    }

    return true;
  }

  public async getIndexBuyTokensTxData() {
    return await this.rpcService.contract(
      await getLatestABI('INDEX_ABI'),
      this.productAddress,
    ).buyTokens.getData();
  }

}
