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

use super::HashMap;
use crate::database_control::*;
use crate::strategy_team::FilteredDataValue;
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
use futures::future::try_join_all;
use serde::Deserialize;
use sqlx::FromRow;
use std::sync::Arc;
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};

#[derive(Clone, Debug)]
pub struct WiliamsPercentR {
    pub r_value: f64,
    pub close_time: i64,
}
impl WiliamsPercentR {
    fn new() -> WiliamsPercentR {
        let a = WiliamsPercentR {
            r_value: 0.0,
            close_time: 0,
        };
        a
    }
}

// Binance Wiliams %R
pub async fn wiliams_percent_r(
    period: usize,
    input_rt_data: &HashMap<String, Vec<RealtimePriceData>>,
    filtered_symbols: &HashMap<String, FilteredDataValue>,
) -> Result<HashMap<String, Vec<WiliamsPercentR>>, Box<dyn std::error::Error + Send + Sync>> {
    if filtered_symbols.is_empty() {
        Err("Err")?;
    }

    let mut wpr_data_wrapper: HashMap<String, Vec<WiliamsPercentR>> = HashMap::new();
    let mut wpr_data_wrapper_arc = Arc::new(Mutex::new(wpr_data_wrapper));

    let mut task_vec = Vec::new();
    for (symbol, filtered_data) in filtered_symbols {
        if let Some(vec) = input_rt_data.get(symbol) {
            let wpr_data_wrapper_arc_c = Arc::clone(&wpr_data_wrapper_arc);
            let symbol_c = symbol.clone();
            let rt_price_data = vec.clone();
            task_vec.push(tokio::spawn(async move {
                let mut wpr_data = WiliamsPercentR::new();
                let mut wpr_data_vec: Vec<WiliamsPercentR> = Vec::new();

                if rt_price_data.len() >= period {
                    let mut iter = rt_price_data.windows(period);
                    for buffer in iter {
                        let highest_high = buffer
                            .iter()
                            .max_by(|x, y| x.high_price.partial_cmp(&y.high_price).unwrap())
                            .unwrap()
                            .high_price;
                        let lowest_low = buffer
                            .iter()
                            .min_by(|x, y| x.low_price.partial_cmp(&y.low_price).unwrap())
                            .unwrap()
                            .low_price;

                        let close_price = buffer.last().unwrap().close_price;
                        let wpr =
                            (highest_high - close_price) / (highest_high - lowest_low) * -100.0;

                        wpr_data.r_value = wpr;
                        wpr_data.close_time = buffer.last().unwrap().close_time;
                        wpr_data_vec.push(wpr_data.clone());
                    }
                }
                let mut wpr_data_wrapper_lock = wpr_data_wrapper_arc_c.lock().await;
                wpr_data_wrapper_lock.insert(symbol_c, wpr_data_vec.clone());
            }));
        }
    }
    try_join_all(task_vec).await?;
    let a = wpr_data_wrapper_arc.lock().await.to_owned();
    Ok(a)
}
