/**
 * Author: dkanus
 * Home repo: https://www.insultplayers.ru/git/AcediaFramework/AcediaCore
 * License: GPL
 * Copyright 2021-2024 Anton Tarasenko
 *------------------------------------------------------------------------------
 * This file is part of Acedia.
 *
 * Acedia is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License, or
 * (at your option) any later version.
 *
 * Acedia is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Acedia.  If not, see <https://www.gnu.org/licenses/>.
 */
class TradingGameplayAPI extends AcediaObject
    abstract;

//! Subset of functionality for dealing with everything related to traders.

/// Describes a cost of an item.
///
/// The money that can be used to buy a single item is described by a set of
/// costs: each cost outlines which currencies and what amounts are necessary to
/// purchase an item.
/// This structure represents one such cost, pairing currencies and costs with
/// the same indices.
struct TradableCost {
    var public array<Text> requiredCurrencies;
    var public int requiredAmounts;
};

var protected SimpleSignal onStartSignal;
var protected SimpleSignal onEndSignal;
var protected Trading_OnSelect_Signal onTraderSelectSignal;

protected function Constructor() {
    onStartSignal = SimpleSignal(_.memory.Allocate(class'SimpleSignal'));
    onEndSignal = SimpleSignal(_.memory.Allocate(class'SimpleSignal'));
    onTraderSelectSignal = Trading_OnSelect_Signal(
        _.memory.Allocate(class'Trading_OnSelect_Signal'));
}

protected function Finalizer() {
    _.memory.Free(onStartSignal);
    _.memory.Free(onEndSignal);
    _.memory.Free(onTraderSelectSignal);
    onStartSignal = none;
    onEndSignal = none;
    onTraderSelectSignal = none;
}

/// Signal that will be emitted whenever trading time starts.
///
/// # Signal signature
///
/// void <slot>()
/* SIGNAL */
public final function SimpleSlot OnStart(AcediaObject receiver) {
    return SimpleSlot(onStartSignal.NewSlot(receiver));
}

/// Signal that will be emitted whenever trading time ends.
///
/// # Signal signature
///
/// void <slot>()
/* SIGNAL */
public final function SimpleSlot OnEnd(AcediaObject receiver) {
    return SimpleSlot(onEndSignal.NewSlot(receiver));
}

/// Signal that will be emitted whenever a new trader is selected.
///
/// # Signal signature
///
/// void <slot>(EPawn target, EPawn instigator, HashTable damageData)
///
/// Parameters [`oldTrader`] and [`newTrader`] refer previously selected and
/// currently (after this event) selected trader respectively.
/// Both arguments are allowed to be `none`.
/* SIGNAL */
public final function Trading_OnSelect_Slot OnTraderSelected(AcediaObject receiver) {
    return Trading_OnSelect_Slot(onTraderSelectSignal.NewSlot(receiver));
}

/// Returns an array with all existing traders on the level, including those
/// that are disabled.
///
/// The array is guaranteed to not contain any `none` references.
public function array<ETrader> GetTraders();

/// Retrieves a trader by the given name `traderName`.
///
/// If multiple traders share the same name, this function returns one
/// arbitrarily.
/// The trader name is case-sensitive.
/// It returns an [`ETrader`] for a valid `traderName` or `none` if no trader
/// matches the name or if the name itself is `none`.
public function ETrader GetTrader(BaseText traderName);

/// Fetches a trader that is currently accessible to the specified player.
///
/// If several traders are accessible, one is chosen at random.
/// This function returns an [`ETrader`] that the specified player can use or
/// `none` if the player cannot use any trader at the moment.
public function ETrader GetTraderFor(EPlayer player);

/// Checks whether trading is currently active in the game.
///
/// In the classic KF game mode, this means it is trader time and one or more
/// traders are open.
/// However, this interface allows trading to be active at any time,
/// independently of game mode conditions.
/// Trading should only be permitted when this function returns active status.
/// This function returns `true` if trading is active and `false` otherwise.
public function bool IsTradingActive();

/// Alters the current status of trading.
///
/// See [`TradingGameplayAPI::IsTradingActive()`] for behavior details.
public function SetTradingStatus(bool makeActive);

/// Returns the duration, in seconds, that the trading period will last.
///
/// In the classic KF game mode, the trading time defaults to 60 seconds.
/// This function returns the duration of the trading period in seconds.
///
/// Returned negative values mean that trading time has no time limit.
public function int GetTradingInterval();

/// Sets the duration of the trading period, in seconds, for the current round.
///
/// This setting affects only the current round and lasts until the end of
/// the map.
/// In the classic KF game mode, it refers to setting the trading time, which
/// defaults to 60 seconds.
/// The [`newTradingInterval`] specifies the new length of the trading period.
///
/// Negative values mean no time limit.
public function SetTradingInterval(int newTradingInterval);

/// Returns the remaining time, in seconds, of the current trading period.
///
/// In the classic KF game mode, this refers to the remaining time for trading.
/// This function indicates how much time is left in the current trading period.
/// It returns `0` if trading is currently inactive.
/// Returned negative values mean that trading is active, but has no time limit.
public function int GetCountdown();

/// Modifies the remaining time, in seconds, of the current trading period.
///
/// This setting can immediately end the trading period if set to `0`.
/// Negative values would disable time limit on the current trading.
/// In the classic KF game mode, this adjustment impacts the ongoing
/// trader time.
public function SetCountdown(int newTradingInterval);

/// Checks if the trading countdown has been paused.
///
/// This pause affects only the current trading period and resets after
/// the period ends.
/// It returns `true` if the countdown is paused and `false` otherwise.
/// If trading is inactive, it also returns `false`.
public function bool IsCountdownPaused();

/// Sets whether the trading countdown should be paused.
///
/// This pause impacts only the current trading period and will reset when
/// the next period starts.
/// The [`doPause`] parameter is `true` to pause the countdown and `false` to
/// resume it.
/// If trading time is currently inactive, this operation does nothing.
public function SetCountdownPause(bool doPause);

/// Retrieves the currently selected trader.
///
/// In classic KF game mode, the selected trader is indicated by the arrow in
/// the HUD's top left corner and by the red wisp during trading time.
/// This interface allows generalization of the selected trader concept to any
/// specially marked trader or avoids using it entirely.
///
/// After calling [`SelectTrader()`], [`GetSelectedTrader()`] should return
/// the specified [`ETrader`].
/// If the selected trader changes through other means, it should trigger
/// the [`OnTraderSelected()`] signal first.
public function ETrader GetSelectedTrader();

/// Changes the currently selected trader.
///
/// Refer to [`GetSelectedTrader()`] for detailed behavior.
public function SelectTrader(ETrader newSelection);

defaultproperties {
}