use crate::error_template::{AppError, ErrorTemplate};
use cfg_if::*;
use leptos::*;
use leptos_meta::*;
use leptos_router::*;

cfg_if! {
    if #[cfg(feature="ssr")]{
        use surrealdb::sql::Thing;
        use surrealdb::Surreal;
        use surrealdb::engine::remote::ws::Ws;
        use surrealdb::opt::auth::Root;
    }
}

#[component]
pub fn App() -> impl IntoView {
    // Provides context that manages stylesheets, titles, meta tags, etc.
    provide_meta_context();

    view! {
        <Link
            rel="stylesheet"
            href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
        />

        <Stylesheet id="leptos" href="/pkg/wallpaper-gen-front-back.css"/>

        // sets the document title
        <Title text="Welcome to Leptos"/>

        // content for this welcome page
        <Router fallback=|| {
            let mut outside_errors = Errors::default();
            outside_errors.insert_with_default_key(AppError::NotFound);
            view! { <ErrorTemplate outside_errors/> }.into_view()
        }>
            <main>
                <Routes>
                    <Route path="/" view=Home/>
                </Routes>
            </main>
        </Router>
    }
}

#[component]
fn Home() -> impl IntoView {
    use leptos::html::Div;
    use leptos_use::*;
    let (size, set_size) = create_signal(1.);
    let (page, set_page) = create_signal(0);
    //let res = create_local_resource(page, get_pics2);
    let (all, set_all) = create_signal(Vec::<PicStruct>::new());
    let res = create_local_resource(
        move || (page.get(), size.get()),
        move |d| get_pics2(d.0, d.1),
    );
    let el = create_node_ref::<Div>();

    let _ = use_infinite_scroll_with_options(
        el,
        move |_| async move {
            if !res.loading().get() && res().is_some() {
                set_page.update(|page| *page += 1);
            }
            res.and_then(move |_| {
                set_all.update(|dat| dat.extend(res().unwrap().unwrap()));
            });
            /*if !res.loading().get() {
                set_page.update(|page| *page += 1);
            } else if res().is_some() {
                set_all.update(|dat| dat.extend(res().unwrap().unwrap()));
                // println!("{:?}", all().len())
            }*/
        },
        UseInfiniteScrollOptions::default().distance(10.0),
    );

    view! {
        <h1>"Home"</h1>
        <div>
            <input
                on:input=move |ev| {
                    set_size(event_target_value(&ev).parse::<f64>().unwrap());
                }

                prop:value=size
                type="range"
                min="0.5"
                max="2"
                step="0.5"
                value="1"
            />
        </div>
        <div class="main overflow-y-auto max-h-300" node_ref=el>
            <For each=move || all.get() key=|state| state.key.clone() let:child>
                <Pic width=child.width height=child.height scale=size url=child.url/>
            </For>
        </div>
        <div class="w-full">
            <p class="text-center">{move || page()}</p>
        </div>
    }
}

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PicStruct {
    key: String,
    width: i32,
    height: i32,
    url: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
struct Wallpaper {
    file_name: String,
    info: String,
    date_added: String,
    height: u64,
    width: u64,
    path: String,
    thumbs: Vec<String>,
}

#[derive(Debug, Serialize)]
struct Name<'a> {
    first: &'a str,
    last: &'a str,
}

#[derive(Debug, Serialize)]
struct Person<'a> {
    title: &'a str,
    name: Name<'a>,
    marketing: bool,
}

#[derive(Debug, Serialize)]
struct Responsibility {
    marketing: bool,
}

#[derive(Debug, Deserialize)]
struct Record {
    #[allow(dead_code)]
    id: i32,
}

use std::env;

#[server(GetPics, "/api")]
pub async fn get_pics2(page: i32, size: f64) -> Result<Vec<PicStruct>, ServerFnError> {
    use image::GenericImageView;
    use imageinfo::ImageInfo;
    use std::fs;
    use std::path::PathBuf;
    // Database setup
    let query = "SELECT * FROM wallpapers LIMIT 10;";
    let db = Surreal::new::<Ws>("127.0.0.1:8000")
        .await
        .expect("Couldn't connect to db server");
    db.use_ns("test")
        .use_db("test")
        .await
        .expect("Couldn't find db");

    let mut res = db.query(query).await?;
    let pap: Vec<Wallpaper> = res.take(0)?;

    let mut pics = Vec::new();
    let folder_path = PathBuf::from("./public/wallpaper-gen-data");
    let pics_per_page = 10;

    let start_index = (page) * pics_per_page;
    let end_index = start_index + pics_per_page;

    let mut image_file_paths = Vec::<PathBuf>::new();

    for entry in fs::read_dir(&folder_path)? {
        let entry = entry?;
        let subfolder_path = entry.path();

        if subfolder_path.is_dir() {
            if let Some(subfolder_name) = subfolder_path.file_name().and_then(|n| n.to_str()) {
                let mut final_path = subfolder_path.clone();

                let file_name = match size {
                    0.5 => format!("{}-thumb-256x146.png", subfolder_name),
                    1.0 => format!("{}-thumb-512x293.png", subfolder_name),
                    1.5 => format!("{}-thumb-1024x585.png", subfolder_name),
                    _ => continue,
                };

                final_path.push(file_name);
                println!("{}", final_path.as_os_str().to_str().unwrap());
                image_file_paths.push(final_path);
            }
        }
    }

    for (i, file_path) in image_file_paths.iter().enumerate() {
        if i < start_index as usize {
            continue;
        }

        if file_path.is_file() {
            let file = std::fs::File::open(file_path)?;
            let mut bufreader = std::io::BufReader::new(&file);

            let exifreader = exif::Reader::new();
            let exif = match exifreader.read_from_container(&mut bufreader) {
                Ok(exif) => Some(exif),
                Err(_) => None, // Handle cases where EXIF data isn't available
            };

            let file_name = file_path.file_name().unwrap_or_default();
            let file_name_str = file_name.to_str().unwrap_or_default();

            if let Some(extension) = file_path.extension() {
                if let Some(extension_str) = extension.to_str() {
                    if image::ImageFormat::from_extension(extension_str).is_some() {
                        // Re-create the BufReader for image processing since it may have been consumed
                        let img = image::open(file_path).expect("Failed to open image");
                        let (x, y) = img.dimensions();

                        pics.push(PicStruct {
                            key: file_name_str.to_string(),
                            width: x as i32,
                            height: y as i32,
                            url: file_name.to_string_lossy().into(),
                        });

                        if i + 1 >= end_index as usize {
                            break;
                        }
                    }
                }
            }
        }
    }

    Ok(pics)
}

#[component]
fn Info(show: ReadSignal<bool>, set_show: WriteSignal<bool>) -> impl IntoView {
    view! {
        <Show when=move || show()>
            <div id="info-main" class="rounded">
                <button type="button" on:click=move |_| set_show(false)>
                    "Close"
                </button>
                <input type="text" id="country" name="country" value="Norway" readonly/>
                <br/>
                <br/>
            </div>
        </Show>
    }
}

#[component]
fn Pic(width: i32, height: i32, url: String, scale: ReadSignal<f64>) -> impl IntoView {
    let (showInfo, set_showInfo) = create_signal(false);

    view! {
        <div
            class="pic-outer"
            // style="border:1px solid black;"
            style:width=move || format!("{}px", f64::from(width + 10))
            style:height=move || format!("{}px", f64::from(height + 10))
        >
            <div
                class="pic-inner"
                style=format!("background-image: url('{}'); background-size: cover;", url)
                style:width=move || format!("{}px", f64::from(width))
                style:height=move || format!("{}px", f64::from(height))
            >
                <div class="dropdown">
                    <button class="dropbtn">
                        <i class="fa-solid fa-download"></i>
                    </button>
                    <div class="dropdown-content">
                        <a href="https://google.com">16:9</a>
                        <a href="#">16:10</a>
                        <a href="#">4:3</a>
                    </div>
                </div>
                <button id="info-button" on:click=move |_| set_showInfo(true)>
                    <i class="fa-regular fa-circle-question"></i>
                </button>
            </div>
        </div>
        <Info show=showInfo set_show=set_showInfo/>
    }
}

