import {Injectable} from '@angular/core';
import {Subject} from 'rxjs';
import {AbstractControl, FormBuilder, FormGroup, Validators} from '@angular/forms';
import {observable, action} from 'mobx-angular';
import {StakeSlpService} from '../core/services/services/stake-slp.service';
import {UtilsService} from '../core/services/services/utils.service';
import {AuthService} from '../core/services/auth/auth.service';
import {takeUntil} from 'rxjs/operators';
import {StatusModalService} from '../shared/services/status-modal.service';



@Injectable({
  providedIn: 'root'
})
export class FormService {


  public formStake: FormGroup;
  public formUnstake: FormGroup;
  private unsubscribe$ = new Subject();

  @observable serverErrorMessage: string;
  @observable isSubmittingApprove = false;
  @observable isSubmittingClaimRewards = false;
  @observable isSubmittingStake = false;
  @observable isSubmittingUnstake = false;
  @observable slpBalance: string;
  @observable staked: string;
  @observable slpAllowance: string;
  @observable rewardsXFT: number;
  @observable rewardsSushi: number;
  @observable apySushi: number;
  @observable apyXFT: number;


  constructor(
    private fb: FormBuilder,
    private stakeSlpService: StakeSlpService,
    private utilsService: UtilsService,
    private authService: AuthService,
    private statusModalService: StatusModalService,
  ) { }

  @action init() {
    this.createFormStake();
    this.createFormUnstake();
    this.getDataFromContract();
  }
  private getDataFromContract() {
    this.stakeSlpService.slpBalanceChange.pipe(takeUntil(this.unsubscribe$)).subscribe((res: string) => {
      this.slpBalance = res;
    });
    this.stakeSlpService.getSLPBalance(this.authService.user.address);

    this.stakeSlpService.stakedChange.pipe(takeUntil(this.unsubscribe$)).subscribe((res: string) => {
      this.staked = res;

    });
    this.stakeSlpService.getStaked(this.authService.user.address);

    this.stakeSlpService.slpAllowanceChange.pipe(takeUntil(this.unsubscribe$)).subscribe((res: string) => {
      this.slpAllowance = res;
    });
    this.stakeSlpService.getSLPAllowance(this.authService.user.address);

    this.stakeSlpService.rewardsXFTChange.pipe(takeUntil(this.unsubscribe$)).subscribe((res: number) => {
      this.rewardsXFT = res;
    });
    this.stakeSlpService.getRewardsXFT(this.authService.user.address);

    this.stakeSlpService.rewardsSushiChange.pipe(takeUntil(this.unsubscribe$)).subscribe((res: number) => {
      this.rewardsSushi = res;
    });
    this.stakeSlpService.getRewardsSushi(this.authService.user.address);

    this.stakeSlpService.apySushiChange.pipe(takeUntil(this.unsubscribe$)).subscribe((res: number) => {
      this.apySushi = res;
    });
    this.stakeSlpService.getAPYSushi(this.authService.user.address);

    this.stakeSlpService.apyXFTChange.pipe(takeUntil(this.unsubscribe$)).subscribe((res: number) => {
      this.apyXFT = res;
    });
    this.stakeSlpService.getAPYXft(this.authService.user.address);


  }

  @action createFormStake() {
    this.formStake = this.fb.group({
      amount: this.fb.control(null, Validators.required),
    });
  }
  @action createFormUnstake() {
    this.formUnstake = this.fb.group({
      amount: this.fb.control(null, Validators.required),
    });
  }

  @action   submitFormStake() {



    if (this.isBlockedFormStake ) {
      return;
    }
    if (this.utilsService.greaterThen(this.stakeAmount.value , this.slpAllowance)) {
      this.isSubmittingApprove = true;
      this.stakeSlpService.approveNewAllowance(
          this.utilsService.convertAmount(this.stakeAmount.value),
          this.authService.user.address
      ).then(() => {
        this.isSubmittingApprove = false;
      }, () => {
        this.isSubmittingApprove = false;
      });
    } else {
      this.isSubmittingStake = true;
      this.stakeSlpService.stake(this.utilsService.convertAmount(this.stakeAmount.value), this.authService.user.address).then((res) => {
        this.isSubmittingStake = false;
        this.formStake.reset();
        this.statusModalService.openStatusModal({hash: res});
      }, () => {
        this.isSubmittingStake = false;
      });
    }
  }
  @action submitFormUnstake() {
    if (this.isBlockedFormUnstake ) {
      return;
    }
    if (this.utilsService.lessOrEqual(this.unstakeAmount.value , this.staked)) {
      this.isSubmittingUnstake = true;
      this.stakeSlpService.unStake(this.utilsService.convertAmount(this.unstakeAmount.value), this.authService.user.address).then((res) => {
        this.isSubmittingUnstake = false;
        this.formUnstake.reset();
        this.statusModalService.openStatusModal({hash: res});
      }, () => {
        this.isSubmittingUnstake = false;
      });
    } else {
      this.isSubmittingUnstake = false;
    }
  }
  @action submitClaimRewards() {
      this.isSubmittingClaimRewards = true;
      this.stakeSlpService.claimReward(this.authService.user.address).then((res) => {
        this.isSubmittingClaimRewards = false;
        this.statusModalService.openStatusModal({hash: res});
      }, () => {
      this.isSubmittingClaimRewards = false;
    });
  }


  get stakeAmount(): AbstractControl {
    return this.formStake.get('amount');
  }
  get unstakeAmount(): AbstractControl {
    return this.formUnstake.get('amount');
  }

  get isBlockedFormStake() {
    return this.formStake.invalid;
  }
  get isBlockedFormUnstake() {
    return this.formUnstake.invalid;
  }


  @action unsubscribe() {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }
}