#![allow(unused)]
#![allow(warnings)]

use crate::database_control::*;
use csv::{DeserializeRecordsIter, StringRecord};
use serde::Deserialize;
use sqlx::FromRow;
use tokio::{fs::*, io::AsyncWriteExt, time::*};

pub async fn tema(
    tema_number: usize,
    input_ema_data: &Vec<(String, Vec<(f64, i64)>)>,
    output_tema_data: &mut Vec<(String, Vec<(f64, i64)>)>,
    valid_usdt_trades: &Vec<String>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let alpha: f64 = 2.0 / (tema_number as f64 + 1.0);
    let mut ema_2order: Vec<f64> = Vec::new();
    let mut ema_3order: Vec<f64> = Vec::new();

    let mut tema_data_wrapper: Vec<(String, Vec<(f64, i64)>)> = Vec::new();
    let mut tema_data_vec: Vec<(f64, i64)> = Vec::new();
    for symbol in valid_usdt_trades {
        let symbol_search_result = input_ema_data.iter().position(|x| x.0 == *symbol);

        tema_data_vec.clear();
        ema_2order.clear();
        ema_3order.clear();

        match symbol_search_result {
            Some(T) => {
                if input_ema_data[T].1.len() < tema_number {
                    tema_data_vec.push((0.0, 0));
                } else {
                    // calculate 2order of ema from 1order of ema
                    let mut ema_prev = 0.0;
                    {
                        let partial_vec1 = input_ema_data[T].1.get(..tema_number).unwrap();
                        let partial_vec2 = input_ema_data[T].1.get(tema_number..).unwrap();

                        let mut sma_for_initial_value = 0.0;
                        for element in partial_vec1 {
                            sma_for_initial_value += element.0;
                        }
                        sma_for_initial_value /= tema_number as f64;
                        ema_2order.push(sma_for_initial_value);
                        ema_prev = sma_for_initial_value;

                        let mut index_2order: usize = 0;
                        for element in partial_vec2 {
                            ema_2order.push(
                                ((1.0 - alpha) * ema_2order[index_2order]) + (alpha * element.0),
                            );
                            index_2order += 1;
                        }
                    }

                    // calculate 3order of ema from 2order of ema
                    let mut index_3order: usize = 0;
                    for element in &ema_2order {
                        if element == ema_2order.first().unwrap() {
                            ema_3order.push(*element);
                        } else {
                            ema_3order.push(
                                ((1.0 - alpha) * ema_3order[index_3order]) + (alpha * (*element)),
                            );
                            index_3order += 1;
                        }
                    }

                    // write string
                    let mut index: usize = 0;
                    let mut tema_price: f64 = 0.0;
                    for element in &input_ema_data[T].1 {
                        tema_price = ((element.0 - ema_2order[index]) * 3.0) + ema_3order[index];
                        tema_data_vec.push((tema_price, element.1));
                        index += 1;
                    }
                    tema_data_wrapper.push((symbol.clone(), tema_data_vec.clone()));
                }
            }
            None => {}
        }
    }
    *output_tema_data = tema_data_wrapper;
    // println!("                                              indicators/tema{}_sec 완료", tema_number);
    Ok(())
}
