use leptos::*;
use validator::Validate;

#[derive(Copy, Clone)]
pub struct Validator {
    //message: ReadSignal<Option<String>>,
    //set_message: WriteSignal<Option<String>>,
    valid: ReadSignal<bool>,
    set_valid: WriteSignal<bool>,
    messages: ReadSignal<Option<Vec<String>>>,
    set_messages: WriteSignal<Option<Vec<String>>>
}

impl Validator {
    pub fn new() -> Self {
        let (valid, set_valid) = create_signal(true);
        //let (message, set_message) = create_signal(None);
        let (messages, set_messages) = create_signal(None);
        Self {
            //message,
            //set_message,
            valid,
            set_valid,
            messages,
            set_messages
        }
    }

    pub fn check(&self, entity: &(impl Validate + ?Sized), ev: &web_sys::Event) {
        if let Err(val_err) = entity.validate() {
            ev.prevent_default();
            //self.set_message.update(|m| *m = Some(val_err.to_string().clone()));
            self.set_messages.update(|m| *m = {
                let mut out: Vec<String> = vec![];
                val_err.field_errors().drain().for_each(|e| {
                    e.1.to_vec().into_iter().for_each(|err| {
                        if let Some(msg) = err.message {
                            out.push(msg.to_string());
                        }
                    });
                });
                Some(out)
            });
            self.set_valid.update(|v| *v = false);
        } else {
            self.set_valid.update(|v| *v = true);
        }
    }

    pub fn is_valid(&self) -> bool {
        self.valid.get()
    }

    /*pub fn message(&self) -> Option<String> {
        self.message.get()
    }*/

    pub fn messages(&self) -> Option<Vec<String>> {
        self.messages.get()
    }

    pub fn reset(&self) {
        self.set_valid.update(|v| *v = true);
    }
}