/*
 * Binance Spot WebSocket API
 *
 * OpenAPI Specifications for the Binance Spot WebSocket API
 *
 * API documents:
 * - [Github web-socket-api documentation file](https://github.com/binance/binance-spot-api-docs/blob/master/web-socket-api.md)
 * - [General API information for web-socket-api on website](https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api/general-api-information)
 *
 *
 * The version of the OpenAPI document: 1.0.0
 *
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

#![allow(unused_imports)]
use crate::spot::websocket_api::models;
use serde::{Deserialize, Deserializer, Serialize, de::Error};
use serde_json::Value;

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(try_from = "Value")]
pub enum UserDataStreamEventsResponse {
    #[serde(rename = "outboundAccountPosition")]
    OutboundAccountPosition(Box<models::OutboundAccountPosition>),
    #[serde(rename = "balanceUpdate")]
    BalanceUpdate(Box<models::BalanceUpdate>),
    #[serde(rename = "executionReport")]
    ExecutionReport(Box<models::ExecutionReport>),
    #[serde(rename = "listStatus")]
    ListStatus(Box<models::ListStatus>),
    #[serde(rename = "eventStreamTerminated")]
    EventStreamTerminated(Box<models::EventStreamTerminated>),
    #[serde(rename = "externalLockUpdate")]
    ExternalLockUpdate(Box<models::ExternalLockUpdate>),
    Other(serde_json::Value),
}

impl Default for UserDataStreamEventsResponse {
    fn default() -> Self {
        Self::OutboundAccountPosition(Default::default())
    }
}

impl TryFrom<Value> for UserDataStreamEventsResponse {
    type Error = serde_json::Error;

    fn try_from(v: Value) -> Result<Self, Self::Error> {
        let tag = v
            .get("e")
            .and_then(Value::as_str)
            .ok_or_else(|| serde_json::Error::custom("missing field `e`"))?;

        match tag {
            "outboundAccountPosition" => {
                let payload = serde_json::from_value(v)?;
                Ok(UserDataStreamEventsResponse::OutboundAccountPosition(
                    Box::new(payload),
                ))
            }

            "balanceUpdate" => {
                let payload = serde_json::from_value(v)?;
                Ok(UserDataStreamEventsResponse::BalanceUpdate(Box::new(
                    payload,
                )))
            }

            "executionReport" => {
                let payload = serde_json::from_value(v)?;
                Ok(UserDataStreamEventsResponse::ExecutionReport(Box::new(
                    payload,
                )))
            }

            "listStatus" => {
                let payload = serde_json::from_value(v)?;
                Ok(UserDataStreamEventsResponse::ListStatus(Box::new(payload)))
            }

            "eventStreamTerminated" => {
                let payload = serde_json::from_value(v)?;
                Ok(UserDataStreamEventsResponse::EventStreamTerminated(
                    Box::new(payload),
                ))
            }

            "externalLockUpdate" => {
                let payload = serde_json::from_value(v)?;
                Ok(UserDataStreamEventsResponse::ExternalLockUpdate(Box::new(
                    payload,
                )))
            }

            _ => Ok(UserDataStreamEventsResponse::Other(v)),
        }
    }
}
