
import { getLatestABI } from '../../services/AbiService';
import { WithdrawService } from '../../services/WithdrawService';
import Mutex from '../../utils/MutexChecker';
import Services from '../../Services';
import { Derivative } from '../Derivative';
import { DerivativeProviders } from '../../interfaces/Enums';

export class DerivativeWithdrawService extends Services {

  private derivativeFunctions: Derivative;
  private productAddress;

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

  public async canWithdraw(): Promise<boolean> {
    const withdrawAddress = await this.derivativeFunctions.getComponentAddress(DerivativeProviders.WITHDRAW);

    const mutex = new Mutex(this.productAddress);
    const productStatusType = mutex.getProductStatusType();

    const mutexResult = await mutex.checkMutex(productStatusType.WITHDRAWING);
    const lockerResult = await mutex.checkLocker(DerivativeProviders.WITHDRAW);

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

    // Check with the withdraw provider whether or not we need to do the withdraw
    if (!await new WithdrawService(this.productAddress).needToWithdraw(this.productAddress, withdrawAddress)) {
      return false;
    }

    // If is closed but there still are requests, still can call

    return true;
  }

  public async getWithdrawTxData() {
    const fundContract = await this.rpcService.contract(await getLatestABI('FUND_ABI'), this.productAddress);
    return await fundContract.withdraw.getData();
  }

}
