import type { BetOption, SlotModel } from './types';
import Locator from '../services/Locator';
import { ANALYTICS_EVENTS } from '../services';

/** View model for the buy bonus dialog and its bet controls. */
export default class BuyBonusViewModel {
    private readonly model: SlotModel;

    private _isMinusButtonPressed = false;
    private _isPlusButtonPressed = false;
    private _bets: number[] = [];
    private _formattedBets: BetOption[] = [];
    private _betFeatureActive = false;

    constructor(model: SlotModel) {
        this.model = model;
    }

    get balance(): number {
        return this.model.balance;
    }

    get currency() {
        return this.model.currency;
    }

    get featureMultipliers() {
        return this.model.featureMultipliers;
    }

    get betFeatureActive(): boolean {
        return Boolean(this.model.betFeatureActive);
    }

    /** Toggle bonus chance (Chance X). */
    toggleBetFeatureActive(): void {
        this.model.toggleBetFeatureActive();

        Locator.analytics.track(ANALYTICS_EVENTS.CHANCE_X_ACTIVATED, {
            enabled: this.model.betFeatureActive,
        });
    }

    buyFreespins(): void {
        this.model.buyFreespins();
        Locator.analytics.track(ANALYTICS_EVENTS.BONUS_BUY_PURCHASED, {
            bonusLevel: 'freespins',
            cost: this.model.resolveFeatureStake(this.model.bet),
            balanceBefore: this.model.balance,
        });
    }

    buyBonus(): void {
        this.model.buyBonus();
        Locator.analytics.track(ANALYTICS_EVENTS.BONUS_BUY_PURCHASED, {
            bonusLevel: 'bonus',
            cost: this.model.resolveFeatureStake(this.model.bet),
            balanceBefore: this.model.balance,
        });
    }

    get bet(): number {
        return this.model.bet;
    }

    set bet(index: number) {
        this.model.setBetByValue(this._bets[index]);
        this._bets = [];
    }

    get bets(): BetOption[] {
        const isBetFeatureActive = this.betFeatureActive;

        if (this._betFeatureActive !== isBetFeatureActive) {
            this._bets = [];
            this._formattedBets = [];
        }
        this._betFeatureActive = isBetFeatureActive;

        if (this.model.bets !== this._bets) {
            this._bets = this.model.bets;
            this._formattedBets = this.model.bets.map((bet) => ({
                value: this.model.currency.getFormattedValue(this.model.resolveFeatureStake(bet)),
                selected: bet === this.model.bet,
                available: this.model.resolveFeatureStake(bet) <= this.model.balance,
            }));
        }

        return this._formattedBets;
    }

    get isMinusButtonPressed(): boolean {
        return this._isMinusButtonPressed;
    }

    set isMinusButtonPressed(value: boolean) {
        if (this._isMinusButtonPressed && !value) {
            this.model.decreaseBet();
            Locator.analytics.track(ANALYTICS_EVENTS.BONUS_BUY_BET_REDUCED, {
                bet: this.model.bet,
            });
            this._bets = [];
        }
        this._isMinusButtonPressed = value;
    }

    get isMinBet(): boolean {
        return this.model.bets.indexOf(this.model.bet) === 0;
    }

    get isPlusButtonPressed(): boolean {
        return this._isPlusButtonPressed;
    }

    set isPlusButtonPressed(value: boolean) {
        if (this._isPlusButtonPressed && !value) {
            this.model.increaseBet();
            Locator.analytics.track(ANALYTICS_EVENTS.BONUS_BUY_BET_INCREASED, {
                bet: this.model.bet,
            });
            this._bets = [];
        }
        this._isPlusButtonPressed = value;
    }

    /** Checks if the next bet would exceed balance after feature multipliers. */
    get isMaxBet(): boolean {
        const betIndex = this.model.bets.indexOf(this.model.bet);
        const maxIndex = this.model.bets.length - 1;
        const isLastBet = betIndex === maxIndex;

        if (isLastBet) return true;

        const nextBet = this.model.bets[betIndex + 1];
        const resolvedNextBet = this.model.resolveFeatureStake(nextBet);
        return resolvedNextBet > this.model.balance;
    }
}
