use serde::Deserialize;
use std::collections::VecDeque;

// By default, struct field names are deserialized based on the position of
// a corresponding field in the CSV data's header record.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct GCTransaction {
    pub(crate) date: String,
    pub(crate) transaction_id: String,
    pub(crate) number: String,
    pub(crate) description: Option<String>,
    pub(crate) notes: Option<String>,
    pub(crate) commodity_currency: Option<String>,
    pub(crate) void_reason: Option<String>,
    pub(crate) action: Option<String>,
    pub(crate) memo: Option<String>,
    pub(crate) full_account_name: Option<String>,
    pub(crate) account_name: Option<String>,
    pub(crate) amount_with_sym: Option<String>,
    pub(crate) amount_num: Option<f32>,
    pub(crate) value_with_sym: Option<String>,
    pub(crate) value_num: Option<f32>,
    pub(crate) reconcile: Option<String>,
    pub(crate) reconcile_date: Option<String>,
    pub(crate) rate_price: Option<String>,
}

impl GCTransaction {
    pub fn set_number(&mut self, number: String) {
        self.number = number;
    }
    pub fn headers() -> [String; 18] {
        [
            "Date".to_owned(),
            "Transaction ID".to_owned(),
            "Number".to_owned(),
            "Description".to_owned(),
            "Notes".to_owned(),
            "Commodity/Currency".to_owned(),
            "Void Reason".to_owned(),
            "Action".to_owned(),
            "Memo".to_owned(),
            "Full Account Name".to_owned(),
            "Account Name".to_owned(),
            "Amount With Sym.".to_owned(),
            "Amount Num".to_owned(),
            "Value With Sym.".to_owned(),
            "Value Num".to_owned(),
            "Reconcile".to_owned(),
            "Reconcile Date".to_owned(),
            "Rate/Price".to_owned(),
        ]
    }
    pub fn output(&self) -> [String; 18] {
        [
            self.date.clone(),
            self.transaction_id.clone(),
            self.number.clone(),
            self.description.clone().unwrap_or_default(),
            self.notes.clone().unwrap_or_default(),
            self.commodity_currency.clone().unwrap_or_default(),
            self.void_reason.clone().unwrap_or_default(),
            self.action.clone().unwrap_or_default(),
            self.memo.clone().unwrap_or_default(),
            self.full_account_name.clone().unwrap_or_default(),
            self.account_name.clone().unwrap_or_default(),
            self.amount_with_sym.clone().unwrap_or_default(),
            match self.amount_num {
                Some(amount_num) => amount_num.to_string().replace('.', ","),
                None => "".to_owned(),
            },
            self.value_with_sym.clone().unwrap_or_default(),
            match &self.value_num {
                Some(value_num) => value_num.to_string().replace('.', ","),
                None => "".to_owned(),
            },
            self.reconcile.clone().unwrap_or_default(),
            self.reconcile_date.clone().unwrap_or_default(),
            self.rate_price.clone().unwrap_or_default(),
        ]
    }
}

pub struct GCTransactionBuffer {
    transactions: VecDeque<GCTransaction>,
}

impl GCTransactionBuffer {
    pub fn new() -> Self {
        Self {
            transactions: VecDeque::new(),
        }
    }
    pub(crate) fn push_back(&mut self, gctransaction: GCTransaction) {
        self.transactions.push_back(gctransaction);
    }
    pub(crate) fn push_front(&mut self, gctransaction: GCTransaction) {
        self.transactions.push_front(gctransaction);
    }
    pub(crate) fn pop_back(&mut self) -> Option<GCTransaction> {
        self.transactions.pop_back()
    }
    pub(crate) fn pop_front(&mut self) -> Option<GCTransaction> {
        self.transactions.pop_front()
    }
    pub(crate) fn iter_mut(&mut self) -> std::collections::vec_deque::IterMut<GCTransaction> {
        self.transactions.iter_mut()
    }
    pub(crate) fn iter(&self) -> std::collections::vec_deque::Iter<GCTransaction> {
        self.transactions.iter()
    }
}