///all Traits
#[allow(warnings)]
pub mod traits {
    use std::thread::JoinHandle;
    use std::{
        any::Any,
        fmt::{Debug, Display},
        path::{Path, PathBuf},
        ptr::null,
        str::FromStr,
    };

    pub trait Spawn<T: Debug> {
        /// ## spawn
        /// ```ignore
        /// use doe::*;
        /// use doe::keyboard::exit_if_click_esc;
        /// let t1 = run.spawn();
        /// let t2 = exit_if_click_esc.spawn();
        /// t1.join();
        /// t2.join();
        /// ```
        ///
        fn spawn(self) -> JoinHandle<T>;
    }
    impl<T: 'static + Send + Debug, F: FnOnce() -> T + Send + 'static> Spawn<T> for F {
        fn spawn(self) -> JoinHandle<T> {
            std::thread::spawn(self)
        }
    }
    pub trait Decimal {
        fn round_to(&self, by: usize) -> Self
        where
            Self: Sized + Copy,
        {
            *self
        }
        fn random() -> Self;
        ///```ignore
        ///  use doe::*;
        ///  f32::random_in_range(0.0..10.0).dprintln();
        ///  i128::random_in_range(10..99).dprintln();
        /// ```
        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self;
        ///num_to_xl_col
        /// ```ignore
        /// use doe::*;
        /// 0.num_to_xl_col().dprintln();
        /// "A".xl_col_to_num().dprintln();
        /// ```
        /// 
        fn num_to_xl_col(&self) -> String;
    }
    impl Decimal for i32 {
        fn num_to_xl_col(&self) -> String{
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;
        
            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }
        
            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as i32
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => i32::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as i32 + min
        }
    }
    impl Decimal for i64 {
        fn num_to_xl_col(&self) -> String{
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;
        
            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }
        
            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as i64
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => i64::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as i64 + min
        }
    }
    impl Decimal for i128 {
        fn num_to_xl_col(&self) -> String{
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;
        
            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }
        
            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as i128
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => i128::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as i128 + min
        }
    }
    impl Decimal for u32 {
        fn num_to_xl_col(&self) -> String{
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;
        
            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }
        
            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as u32
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => u32::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as u32 + min
        }
    }
    impl Decimal for u64 {
        fn num_to_xl_col(&self) -> String{
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;
        
            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }
        
            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as u64
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => u64::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as u64 + min
        }
    }

    impl Decimal for u128 {
        fn num_to_xl_col(&self) -> String{
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;
        
            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }
        
            result.chars().rev().collect()
        }
        fn random() -> Self {
            (LCG::new().random() * 10.0) as u128
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => u128::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub as f64) as u128 + min
        }
    }
    impl Decimal for f64 {
        fn num_to_xl_col(&self) -> String{
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;
        
            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }
        
            result.chars().rev().collect()
        }
        fn round_to(&self, by: usize) -> f64 {
            let factor = 10.0_f64.powi(by as i32);
            (self * factor).round() / factor
        }
        fn random() -> Self {
            LCG::new().random()
        }

        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0.0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => f64::MAX,
            };

            let random = LCG::new().random();
            let sub = max - min;
            (random * sub) + min
        }
    }

    impl Decimal for f32 {
        fn num_to_xl_col(&self) -> String{
            let index = *self as usize + 1;
            let mut result = String::new();
            let mut index = index;
        
            while index > 0 {
                let remainder = (index - 1) % 26;
                result.push((b'A' + remainder as u8) as char);
                index = (index - 1) / 26;
            }
        
            result.chars().rev().collect()
        }
        
        fn round_to(&self, by: usize) -> f32 {
            let factor = 10.0_f32.powi(by as i32);
            (self * factor).round() / factor
        }
        fn random() -> Self {
            LCG::new().random_f32()
        }
        fn random_in_range<R: std::ops::RangeBounds<Self>>(range: R) -> Self {
            let min = match range.start_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => 0.0,
            };

            let max = match range.end_bound() {
                std::ops::Bound::Included(v) => *v,
                std::ops::Bound::Excluded(v) => *v,
                std::ops::Bound::Unbounded => f32::MAX,
            };

            let random = LCG::new().random_f32();
            let sub = max - min;
            (random * sub) + min
        }
    }

    pub trait DynType: ToString {}
    impl<T: ToString> DynType for T {}
    /// this is a ToStringWrapper Struct for implementing Into to Box<dyn DynType>
    #[derive(Debug, Clone)]
    pub struct ToDynType<T: ToString>(pub T);
    impl<T: ToString> Into<Box<dyn DynType>> for ToDynType<T> {
        fn into(self) -> Box<dyn DynType> {
            Box::new(self.0.to_string())
        }
    }
    use std::ops::Deref;

    use crate::LCG;
    pub trait Join {
        fn join(&self, by: &str) -> String;
    }

    impl<T: ToString> Join for [T] {
        fn join(&self, by: &str) -> String {
            self.iter()
                .map(|item| item.to_string())
                .collect::<Vec<String>>()
                .join(by)
        }
    }

    pub trait Vector<T> {
        fn element_to_string(&self) -> Vec<String>;
        fn to_string_lossy(&self) -> String;
        fn split_by_slice(&self, slice: &[T]) -> Vec<Vec<T>>;
        fn random_choose(&self) -> T;
    }
    impl<T: ToString + PartialEq + Clone> Vector<T> for [T] {
        fn element_to_string(&self) -> Vec<String> {
            self.iter().map(|x| x.to_string()).collect::<Vec<String>>()
        }

        fn to_string_lossy(&self) -> String {
            let vec = self
                .iter()
                .map(|x| x.to_string().parse::<u8>().unwrap())
                .collect::<Vec<u8>>();
            String::from_utf8_lossy(&vec).to_string()
        }

        fn split_by_slice(&self, slice: &[T]) -> Vec<Vec<T>> {
            let mut result = Vec::new();
            let mut start = 0;

            while let Some(index) = self[start..]
                .windows(slice.len())
                .position(|window| window == slice)
            {
                let end = start + index;
                result.push(self[start..end].to_vec());
                start = end + slice.len();
            }

            result.push(self[start..].to_vec());

            result
        }

        ///random_choose
        ///```rust
        ///use doe::*;  
        ///let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        ///v.random_choose().dprintln();
        /// ```
        ///
        fn random_choose(&self) -> T {
            use crate::LCG;
            let lcg = LCG::new();
            let random_index = lcg.random_in_range(0..self.len() as i128);
            self.clone().get(random_index as usize).unwrap().to_owned()
        }
    }
    pub trait Str {
        fn cut(&self, start: i32, end: i32, step: usize) -> String;

        fn format(&self, targets: Vec<(Box<dyn ToString>, Box<dyn ToString>)>) -> String;
        /// str String to Path
        fn to_path(&self) -> Box<Path>;
        /// str String to PathBuf
        fn to_path_buf(&self) -> PathBuf;
        ///split string by delimiter into Vec<String>
        fn split_to_vec(&self, delimiter: &str) -> Vec<String>;
        ///string into Box<str>
        fn to_box(&self) -> Box<str>;
        ///push back item to string
        fn push_back(&self, item: impl ToString) -> String;
        ///push front item to string
        fn push_front(&self, item: impl ToString) -> String;
        ///is equal return true
        fn is_equal(&self, other: &Self) -> bool;
        //add two string
        fn add(&self, other: &Self) -> String;
        //reverse string
        fn reverse(&self) -> String;
        //capitalize string
        fn capitalize(&self) -> String;
        /// trim start of string
        fn trim_lines(&self) -> String;
        /// convert xl col to num
        /// ```ignore
        /// use doe::*;
        /// 0.num_to_xl_col().dprintln();
        /// "A".xl_col_to_num().dprintln();
        /// ```
        /// 
        fn xl_col_to_num(&self) -> usize;
        /// convert 'A1' to (col, row) = (0,1)
        fn coordinate_to_position(&self) -> (usize, usize);
    }

    impl<S: ToString> Str for S {
        fn coordinate_to_position(&self) -> (usize, usize){
            let coord_str = self.to_string();
            let mut col_str = String::new();
            let mut row_str = String::new();
            for c in coord_str.chars() {
                if c.is_digit(10) {
                    row_str.push(c);
                } else {
                    col_str.push(c);
                }
            }
            let col_num = col_str.xl_col_to_num();
            let row_num = row_str.parse::<usize>().unwrap();
            (col_num, row_num)
        }
        fn xl_col_to_num(&self) -> usize{
            let col_str = self.to_string().to_uppercase();
            let mut col_num = 0;
            for (i, c) in col_str.chars().enumerate() {
                if (c as u8 as i8 - 'A' as u8 as i8) >= 0 {
                    let offset = (c as u8 - b'A') as usize + 1;
                    col_num = col_num * 26 + offset;
                }
            }
            col_num -1
        }
        //add two string
        fn add(&self, other: &Self) -> String {
            format!("{}{}", self.to_string(), other.to_string())
        }
        ///is equal return true
        fn is_equal(&self, other: &Self) -> bool {
            self.to_string() == other.to_string()
        }
        ///push back item to string
        fn push_back(&self, item: impl ToString) -> String {
            format!("{}{}", self.to_string(), item.to_string())
        }

        ///push front item to string
        fn push_front(&self, item: impl ToString) -> String {
            format!("{}{}", item.to_string(), self.to_string().to_string())
        }
        /// ## implment cut format for str and String
        /// ```rust
        ///fn main() {
        ///    use doe::Str;
        ///    use doe::targets;
        ///    let a = "this is a demo {}";
        ///    let c = a.cut(-1,-2,1);
        ///    let f = a.format(targets!("{}"=>"this is a demo"));
        ///    println!("{:?}",f);
        ///    println!("{:?}",c);
        ///}
        /// ```
        fn cut(&self, start: i32, end: i32, step: usize) -> String {
            let mut res = String::new();
            if start >= 0 && end >= 0 && start <= end {
                let start = start as usize;
                let end = end as usize;
                for (i, c) in self.to_string().chars().enumerate().step_by(step) {
                    if i >= start && i <= end {
                        res.push(c);
                    }
                }
            } else if start < 0 && end < 0 {
                if start > end {
                    let start = self.to_string().len() as i32 + end;
                    let end = self.to_string().len() as i32 + start;
                    let start = start as usize;
                    let end = end as usize;
                    for (i, c) in self.to_string().chars().enumerate().step_by(step) {
                        if i >= start && i <= end {
                            res.push(c);
                        }
                    }
                } else {
                    let start = self.to_string().len() as i32 + start;
                    let end = self.to_string().len() as i32 + end;
                    let start = start as usize;
                    let end = end as usize;
                    for (i, c) in self.to_string().chars().enumerate().step_by(step) {
                        if i >= start && i <= end {
                            res.push(c);
                        }
                    }
                }
            } else if start > 0 && end < 0 {
                let start = start as usize;
                let end = self.to_string().len() as i32 + end;
                let end = end as usize;
                for (i, c) in self.to_string().chars().enumerate().step_by(step) {
                    if i >= start && i <= end {
                        res.push(c);
                    }
                }
            }
            res
        }

        /// ## implment format for str and String
        /// ```rust
        ///fn main() {
        ///    use doe::*;
        ///    "this is a {s},I like Trait Object {p}%"
        ///    .format(vec![(Box::new("{s}"),Box::new("demo")),(Box::new("{p}"),Box::new(100))]).println();//this is a demo,I like Trait Object 100%
        ///     use doe::targets;
        ///     "this is a {d},I like Trait Object {p}}%"
        ///     .format(targets!{"{d}"=>"demo","{p}"=>100})
        ///     .println(); //this is a demo,I like Trait Object 100%
        ///     
        ///     let a = "demo";
        ///     let b_a: Box<str> = a.to_box();
        ///     b_a.as_ref().dprintln();
        ///}
        /// ```
        fn format(&self, targets: Vec<(Box<dyn ToString>, Box<dyn ToString>)>) -> String {
            let mut s_mut = self.to_string().to_string();
            for t in targets {
                s_mut = s_mut.replace(&t.0.deref().to_string(), &t.1.deref().to_string());
            }
            s_mut
        }
        fn to_path(&self) -> Box<Path> {
            Path::new(&self.to_string()).to_owned().into()
        }
        fn to_path_buf(&self) -> PathBuf {
            PathBuf::from_str(&self.to_string()).unwrap()
        }
        fn split_to_vec(&self, delimiter: &str) -> Vec<String> {
            crate::split_to_vec!(self.to_string(), delimiter)
        }
        fn to_box(&self) -> Box<str> {
            Box::from(self.to_string())
        }
        ///reverse string
        /// ```rust
        /// use doe::Str;
        /// use doe::*;
        /// "a string".reverse().println(); //"gnirts a"
        /// ```
        ///
        fn reverse(&self) -> String {
            let mut s = self.to_string().chars().rev().collect::<Vec<_>>();
            s.join("")
        }
        //capitalize string
        fn capitalize(&self) -> String {
            if let Some(c) = self.to_string().chars().next() {
                let first_letter_capitalized = c.to_uppercase().collect::<String>();
                let rest_of_string = &self.to_string()[1..];
                return format!("{}{}", first_letter_capitalized, rest_of_string);
            }
            self.to_string()
        }

        fn trim_lines(&self) -> String {
            self.split_to_vec("\n")
                .iter()
                .map(|s| s.trim().to_string())
                .collect::<Vec<_>>()
                .join("\n")
        }
    }
    pub trait Then {
        fn then(&self, run: impl Fn()) -> &Self;
    }

    impl<T> Then for T {
        fn then(&self, run: impl Fn()) -> &Self {
            run();
            self
        }
    }
    pub trait Sleep {
        fn sleep(&self, secs: f64);
    }
    impl<T> Sleep for T {
        fn sleep(&self, secs: f64) {
            use std::thread::sleep;
            use std::time::Duration;
            sleep(Duration::from_secs_f64(secs));
        }
    }

    /// A trait for impl Debug
    pub trait DebugPrint {
        /// debug print
        /// ```rust
        /// use doe::DebugPrint;
        /// let get = |url:&str|url.to_string().dprint();
        /// ```
        fn dprint(&self);
        /// debug eprint
        /// ```rust
        /// use doe::DebugPrint;
        /// let get = |url:&str|url.to_string().deprint();
        /// ```
        fn deprint(&self);
        /// debug println
        /// ```rust
        /// use doe::DebugPrint;
        /// let get = |url:&str|url.to_string().dprintln();
        /// ```
        fn dprintln(&self);
        /// debug eprintln
        /// ```rust
        /// use doe::DebugPrint;
        /// let get = |url:&str|url.to_string().deprintln();
        /// ```
        fn deprintln(&self);
        /// ```rust
        /// fn main() {
        ///     use doe::DebugPrint;
        ///     #[derive(Debug)]
        ///     struct Demo{}
        ///     let d = Demo{};
        ///     d.dbg();
        /// }
        /// ```
        fn dbg(&self);
    }
    impl<T> DebugPrint for T
    where
        T: Debug,
    {
        fn dprint(&self) {
            print!("{:?}", self);
        }
        fn deprint(&self) {
            eprint!("{:?}", self);
        }

        fn dprintln(&self) {
            println!("{:?}", self);
        }
        fn deprintln(&self) {
            eprintln!("{:?}", self);
        }
        fn dbg(&self) {
            dbg!(self);
        }
    }
    pub trait Print {
        /// ```rust
        /// use doe::Print;
        /// let get = |url:&str|url.to_string().print();
        /// ```
        fn print(&self);
        /// ```rust
        /// use doe::Print;
        /// let get = |url:&str|url.to_string().print();
        /// ```
        fn eprint(&self);
        /// ```rust
        /// use doe::Print;
        /// let get = |url:&str|url.to_string().println();
        /// ```
        fn println(&self);
        /// ```rust
        /// use doe::Print;
        /// let get = |url:&str|url.to_string().println();
        /// ```
        fn eprintln(&self);
    }
    impl<T> Print for T
    where
        T: Display,
    {
        fn print(&self) {
            print!("{}", self);
        }
        fn eprint(&self) {
            eprint!("{}", self);
        }

        fn println(&self) {
            println!("{}", self);
        }
        fn eprintln(&self) {
            eprintln!("{}", self);
        }
    }
    ///IsThen
    /// ```rust
    ///use doe::*;
    ///let a = Some(1);
    ///let b: Result<i32, Box<dyn std::error::Error>> = Err("error".into());
    ///b.is_ok_then(|s| {
    ///}).is_none_then(|| {
    ///    println!("NONE");
    ///});
    /// ```
    pub trait IsThen<T> {
        fn is_some_then(self, f: impl FnOnce(T) -> T) -> Option<T>;
        fn is_none_then(self, f: impl FnOnce());
        fn is_ok_then(self, f: impl FnOnce(T)) -> Option<T>;
        fn is_err_then(self, f: impl FnOnce());
    }

    impl<T: Clone, U> IsThen<T> for Result<T, U> {
        fn is_some_then(self, f: impl FnOnce(T) -> T) -> Option<T> {
            match self {
                Ok(value) => Some(f(value)),
                Err(_) => None,
            }
        }

        fn is_none_then(self, f: impl FnOnce()) {
            if self.is_err() {
                f();
            }
        }

        fn is_ok_then(self, f: impl FnOnce(T)) -> Option<T> {
            match self {
                Ok(value) => {
                    f(value.clone());
                    Some(value)
                }
                Err(_) => None,
            }
        }

        fn is_err_then(self, f: impl FnOnce()) {
            if self.is_err() {
                f();
            }
        }
    }

    impl<T: Clone> IsThen<T> for Option<T> {
        fn is_some_then(self, f: impl FnOnce(T) -> T) -> Option<T> {
            match self {
                Some(value) => Some(f(value)),
                None => None,
            }
        }

        fn is_none_then(self, f: impl FnOnce()) {
            if self.is_none() {
                f();
            }
        }

        fn is_ok_then(self, f: impl FnOnce(T)) -> Option<T> {
            match self {
                Some(value) => {
                    f(value.clone());
                    Some(value)
                }
                None => None,
            }
        }

        fn is_err_then(self, f: impl FnOnce()) {
            if self.is_none() {
                f();
            }
        }
    }
}
