use num_bigint::BigUint;
use serde::{Deserialize, Serialize};

use crate::{AssetAmount, AssetId, MarketId, WalletRegisterId};

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct MarketTradingFee {
    /// Orderbook taker fee
    /// Swap fee is the same as orderbook taker fee
    pub taker_fee: BigUint,
    pub maker_fee: BigUint,
    pub fee_decimal: u8,
}

/// Orderbook price limitation
/// # Example
/// ```rust
/// use num_bigint::BigUint;
/// use ex3_canister_types::transaction::market::OrderPriceLimitation;
/// let latest_order_price: BigUint = BigUint::from(1000000000u32);
/// let order_price_limitation = OrderPriceLimitation {
///    bid_price_rate_cap: BigUint::from(3000000000u32),
///    ask_price_rate_floor: BigUint::from(20000000u32),
///    rate_decimal: 8,
/// };
/// let real_bid_price_rate_cap : f64 = order_price_limitation.bid_price_rate_cap.clone() / BigUint::from(10u32.pow(order_price_limitation.rate_decimal as u32));
/// assert_eq!(real_bid_price_rate_cap, 3.0);
/// ```
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct OrderPriceLimitation {
    /// Orderbook biding price rate cap
    pub bid_price_rate_cap: BigUint,
    /// Orderbook asking price rate floor
    pub ask_price_rate_floor: BigUint,
    /// Price rate decimal
    pub rate_decimal: u8,
}

/// Market settings
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct MarketSettings {
    /// Trading fee
    pub fee: MarketTradingFee,

    /// Fee to
    /// Orderbook fee to & swap fee to use this value
    /// Note: fee to will receive the market trading fee
    /// Note: if the fee to is none, the market trading fee will be sent to the default fee to
    pub fee_to: Option<WalletRegisterId>,

    /// Price max decimal
    /// Orderbook price decimal & swap price decimal use this value
    pub price_max_decimal: u8,

    /// Volume max decimal
    /// Orderbook volume decimal & swap volume decimal use this value
    /// Note: volume means base asset quantity
    pub volume_max_decimal: u8,

    /// Min order amount
    /// Orderbook min order amount & swap min order amount use this value
    /// Note: amount means quota asset quantity
    pub min_order_amount: AssetAmount,

    /// Min order volume
    /// Orderbook min order volume & swap min order volume use this value
    /// Note: volume means base asset quantity
    pub min_order_volume: AssetAmount,

    /// Price limitation
    pub price_limitation: OrderPriceLimitation,

    /// AMM V2 fee taking ratio
    /// # Range
    /// 0 ~ 100
    /// # Example
    /// * 0: 0%
    /// * 100: 100%
    /// # Note
    /// This value is used for AMM V2
    pub amm_v2_fee_taking_ratio: u8,
}

/// Register market
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct RegisterMarket {
    /// Base asset id
    pub base_asset_id: AssetId,

    /// Base asset quantity
    pub base_asset_quantity: AssetAmount,

    /// Quote asset id
    pub quote_asset_id: AssetId,

    /// Quote asset quantity
    pub quote_asset_quantity: AssetAmount,

    /// Market settings
    pub settings: MarketSettings,
}

/// Update market settings
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct UpdateMarketSettings {
    /// Market id
    pub market_id: MarketId,

    /// Market settings
    pub settings: MarketSettings,
}
