use crate::locales::trl;
use leptos::*;
use crate::app::DialogHelper;
use crate::validator::Validator;

#[derive(Copy, Clone)]
pub struct DialogOpener {
    visible: ReadSignal<bool>,
    set_visible: WriteSignal<bool>,
    empty: ReadSignal<String>,
    set_empty: WriteSignal<String>,
    not_checked: ReadSignal<Option<String>>,
    set_not_checked: WriteSignal<Option<String>>,
    show_err: RwSignal<bool>
}

impl DialogOpener {
    pub fn new() -> Self {
        let (visible, set_visible) = create_signal(false);
        let (empty, set_empty) = create_signal("".to_string());
        let (not_checked, set_not_checked) = create_signal(None);
        let show_err = create_rw_signal(false);
        DialogOpener {
            visible,
            set_visible,
            empty,
            set_empty,
            not_checked,
            set_not_checked,
            show_err
        }
    }

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

    pub fn show(&self) {
        let dlg_helper = use_context::<DialogHelper>().expect("No dialog helper");
        dlg_helper.set_opened(true);
        self.set_visible.update(|state| *state = true);
    }

    pub fn hide(&self) {
        let dlg_helper = use_context::<DialogHelper>().expect("No dialog helper");
        dlg_helper.set_opened(false);
        self.set_visible.update(|state| *state = false);
        self.set_empty.set("".to_string());
        self.set_not_checked.set(None);
        self.show_err.set(false);
    }

    pub fn empty(&self) -> String {
        self.empty.get()
    }

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

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

    pub fn display_err(&self) {
        self.show_err.set(true);
    }
}

#[component]
pub fn ModalDialog(
    opener: DialogOpener,
    title: &'static str,
    #[prop(optional)]
    validator: Option<Validator>,
    children: Children,
) -> impl IntoView {
    view! {
        <div class={ move || if opener.visible() {"modal fade show"} else {"modal fade"}}
            style={ move || if opener.visible() {"display: block;"} else {""}}
            id="modalCenter" tabindex="-1" aria-hidden="true">
            <div class="modal-dialog modal-dialog-centered" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="modalCenterTitle">{trl(title)}</h5>
                        <button
                            type="button"
                            class="btn-close"
                            data-bs-dismiss="modal"
                            aria-label="Close"
                            on:click=move |_| {
                                if let Some(v) = validator {
                                    v.reset();
                                }
                                opener.hide();
                            }/>
                        </div>
                        {children()}
                    </div>
                </div>
            </div>
    }
}

#[component]
pub fn ModalBody(children: Children) -> impl IntoView {
    view! {
        <div class="modal-body">
            {children()}
        </div>
    }
}

#[component]
pub fn ModalFooter(children: Children) -> impl IntoView {
    view! {
        <div class="modal-footer">
           {children()}
        </div>
    }
}

#[component]
pub fn DlgNotLoaded(opener: DialogOpener, title: &'static str) -> impl IntoView {
    view! {
        <ModalDialog opener=opener title=title>
        <ModalBody>
            <div>{trl("Entity not loaded")}</div>
        </ModalBody>
        <ModalFooter>
            <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal" on:click=move |_| opener.hide()>
                {trl("Close")}
            </button>
        </ModalFooter>
        </ModalDialog>
    }
}
