/*
 * Ethereal Exchange API
 *
 * Ethereal HTTP API for real-time trading, order management, and market data access.
 *
 * The version of the OpenAPI document: 0.1.0
 *
 * Generated by: https://openapi-generator.tech
 */

use crate::models;
use serde::{Deserialize, Serialize};

#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct OrderDto {
    /// Id representing the order
    #[serde(rename = "id")]
    pub id: uuid::Uuid,
    /// A subaccount scoped unique client-generated order id (either a UUID or alphanumeric string up to 32 characters)
    #[serde(rename = "clientOrderId", skip_serializing_if = "Option::is_none")]
    pub client_order_id: Option<String>,
    /// Trade order type e.g. MARKET or LIMIT
    #[serde(rename = "type")]
    pub r#type: Type,
    /// Remaining quantity (if modified or reduced) in native units expressed as a decimal (precision: 9)
    #[serde(rename = "availableQuantity")]
    pub available_quantity: String,
    /// Original quantity (as per order submission) in native units expressed as a decimal (precision: 9)
    #[serde(rename = "quantity")]
    pub quantity: String,
    #[serde(rename = "side")]
    pub side: models::OrderSide,
    /// Id of product this order was placed against
    #[serde(rename = "productId")]
    pub product_id: uuid::Uuid,
    /// Id of the subaccount associated to order
    #[serde(rename = "subaccountId")]
    pub subaccount_id: uuid::Uuid,
    #[serde(rename = "status")]
    pub status: models::OrderStatus,
    /// Indicates if the order is reduce only
    #[serde(rename = "reduceOnly")]
    pub reduce_only: bool,
    /// Order closes the entire current position
    #[serde(rename = "close")]
    pub close: bool,
    /// Order last updated timestamp (ms since Unix Epoch)
    #[serde(rename = "updatedAt")]
    pub updated_at: f64,
    /// Order creation timestamp (ms since Unix Epoch)
    #[serde(rename = "createdAt")]
    pub created_at: f64,
    /// Account or linked signer address that placed this order
    #[serde(rename = "sender")]
    pub sender: String,
    /// Limit price in native units expressed as a decimal, zero if market order (precision: 9)
    #[serde(rename = "price")]
    pub price: String,
    /// Filled amount in native units expressed as a decimal (precision: 9)
    #[serde(rename = "filled")]
    pub filled: String,
    /// Stop price expressed as a decimal (zero if not a stop order, precision: 9)
    #[serde(rename = "stopPrice")]
    pub stop_price: String,
    /// Side as either BUY (0) or SELL (1)
    #[serde(rename = "stopType", skip_serializing_if = "Option::is_none")]
    pub stop_type: Option<StopType>,
    /// Type of stop price (stop orders only)
    #[serde(rename = "stopPriceType", skip_serializing_if = "Option::is_none")]
    pub stop_price_type: Option<StopPriceType>,
    /// How long an order will remain until executed/expired (required if limit)
    #[serde(rename = "timeInForce", skip_serializing_if = "Option::is_none")]
    pub time_in_force: Option<TimeInForce>,
    /// Order expiry timestamp (seconds since Unix Epoch)
    #[serde(rename = "expiresAt")]
    pub expires_at: f64,
    /// Only add order if it does not immediately fill (limit only)
    #[serde(rename = "postOnly", skip_serializing_if = "Option::is_none")]
    pub post_only: Option<bool>,
    /// Type of OTOCO relationship (OTO or OCO)
    #[serde(
        rename = "groupContingencyType",
        skip_serializing_if = "Option::is_none"
    )]
    pub group_contingency_type: Option<GroupContingencyType>,
    /// Id of the group this order belongs to
    #[serde(rename = "groupId", skip_serializing_if = "Option::is_none")]
    pub group_id: Option<uuid::Uuid>,
}

impl OrderDto {
    pub fn new(
        id: uuid::Uuid,
        r#type: Type,
        available_quantity: String,
        quantity: String,
        side: models::OrderSide,
        product_id: uuid::Uuid,
        subaccount_id: uuid::Uuid,
        status: models::OrderStatus,
        reduce_only: bool,
        close: bool,
        updated_at: f64,
        created_at: f64,
        sender: String,
        price: String,
        filled: String,
        stop_price: String,
        expires_at: f64,
    ) -> OrderDto {
        OrderDto {
            id,
            client_order_id: None,
            r#type,
            available_quantity,
            quantity,
            side,
            product_id,
            subaccount_id,
            status,
            reduce_only,
            close,
            updated_at,
            created_at,
            sender,
            price,
            filled,
            stop_price,
            stop_type: None,
            stop_price_type: None,
            time_in_force: None,
            expires_at,
            post_only: None,
            group_contingency_type: None,
            group_id: None,
        }
    }
}
/// Trade order type e.g. MARKET or LIMIT
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Type {
    #[serde(rename = "MARKET")]
    Market,
    #[serde(rename = "LIMIT")]
    Limit,
}

impl Default for Type {
    fn default() -> Type {
        Self::Market
    }
}
/// Side as either BUY (0) or SELL (1)
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum StopType {
    #[serde(rename = "0")]
    GAIN,
    #[serde(rename = "1")]
    LOSS,
}

impl Default for StopType {
    fn default() -> StopType {
        Self::GAIN
    }
}
/// Type of stop price (stop orders only)
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum StopPriceType {
    #[serde(rename = "0")]
    LAST_PRICE,
    #[serde(rename = "1")]
    MARK_PRICE,
}

impl Default for StopPriceType {
    fn default() -> StopPriceType {
        Self::LAST_PRICE
    }
}
/// How long an order will remain until executed/expired (required if limit)
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum TimeInForce {
    #[serde(rename = "GTD")]
    Gtd,
    #[serde(rename = "IOC")]
    Ioc,
    #[serde(rename = "FOK")]
    Fok,
}

impl Default for TimeInForce {
    fn default() -> TimeInForce {
        Self::Gtd
    }
}
/// Type of OTOCO relationship (OTO or OCO)
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum GroupContingencyType {
    #[serde(rename = "0")]
    OTO,
    #[serde(rename = "1")]
    OCO,
}

impl Default for GroupContingencyType {
    fn default() -> GroupContingencyType {
        Self::OTO
    }
}
