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;

    let query = "
        SELECT * FROM wallpapers LIMIT 10;
        ";

    let db = Surreal::new::<Ws>("127.0.0.1:8000")
        .await
        .expect("Couldnt connect to db server");
    // Select a specific namespace / database
    db.use_ns("test")
        .use_db("test")
        .await
        .expect("Couldnt find db");
    //let papers: Vec<Wallpaper> = db.select("wallpapers").await.expect("Err");
    //println!("{papers:#?}");

    let mut res = db.query(query).await?;
    let pap: Vec<Wallpaper> = res.take(0)?;
    println!("{pap:#?}");

    let mut pics = Vec::new();

    let folder_path = "./public";

    // Define the number of pictures per page
    let pics_per_page = 10;

    // Calculate the index to start from based on the page number
    let start_index = (page) * pics_per_page;
    let end_index = start_index + pics_per_page;

    // manage a vector with all the image paths
    let mut image_file_paths = Vec::<PathBuf>::new();
    for entry in fs::read_dir(folder_path)? {
        let entry = entry?;
        let file_path = entry.path();
        let file_name_str = file_path.file_name().unwrap_or_default().to_str().unwrap();
        if size == 0.5 {
            //skip 1024 and 512
            if file_name_str.contains("512x512") || file_name_str.contains("1024x1024") {
                continue;
            }
        } else if size == 1.0 {
            if file_name_str.contains("256x256") || file_name_str.contains("1024x1024") {
                println!("sdfasdf");
                continue;
            }
        } else if size == 1.5 {
            if file_name_str.contains("256x256") || file_name_str.contains("512x512") {
                continue;
            }
        }
        image_file_paths.push(file_path.clone());
    }

    for (i, file_path) in image_file_paths.iter().enumerate() {
        if file_path.is_file() {
            if i < start_index as usize {
                continue;
            }
            let file = std::fs::File::open(file_path)?;
            let mut bufreader = std::io::BufReader::new(&file);
            let exifreader = exif::Reader::new();
            let exif = exifreader.read_from_container(&mut bufreader)?;
            for f in exif.fields() {
                println!(
                    "{} {} {}",
                    f.tag,
                    f.ifd_num,
                    f.display_value().with_unit(&exif)
                );
            }
            let file_name = file_path.file_name().unwrap_or_default();
            let file_name_str = file_name.to_str().unwrap();
            // Check if the file has a supported image extension
            if let Some(extension) = file_path.extension() {
                if let Some(extension_str) = extension.to_str() {
                    if image::ImageFormat::from_extension(extension_str).is_some() {
                        // Process the image
                        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(), // Could not be unique if two images were created at exactly
                            // the same time
                            width: x as i32,
                            height: y as i32,
                            url: file_name.to_string_lossy().into(),
                        });
                        if i + 1 >= end_index as usize {
                            break;
                        }
                    }
                }
            }
        }
    }

    // Send different picture resolutions depending on selected size
    // sizes 256 512 1024

    // Iterate over the entries in the folder
    /*for (index, entry) in fs::read_dir(folder_path)
        .expect("Failed to read directory")
        .enumerate()
    {
        if let Ok(entry) = entry {
            if index < start_index as usize {
                // Skip pictures before the start index
                continue;
            }

            let file_path = entry.path();
            let file_name = file_path.file_name().unwrap_or_default();
            let file_name_str = file_name.to_str().unwrap();
            // Skip the wrong sizes
            if size == 0.5 {
                //skip 1024 and 512
                if file_name_str.contains("512x512") || file_name_str.contains("1024x1024") {
                    continue;
                }
            } else if size == 1.0 {
                if file_name_str.contains("256x256") || file_name_str.contains("1024x1024") {
                    continue;
                }
            } else if size == 1.5 {
                if file_name_str.contains("256x256") || file_name_str.contains("512x512") {
                    continue;
                }
            }

            // Check if the entry is a file
            if file_path.is_file() {
                // Check if the file has a supported image extension
                if let Some(extension) = file_path.extension() {
                    if let Some(extension_str) = extension.to_str() {
                        if image::ImageFormat::from_extension(extension_str).is_some() {
                            // Process the image
                            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(), // Could not be unique if two images were created at exactly
                                // the same time
                                width: x as i32,
                                height: y as i32,
                                url: file_name.to_string_lossy().into(),
                            });

                            // Break if we have reached the end index
                            if index + 1 >= end_index as usize {
                                break;
                            }
                        }
                    }
                }
            }
        }
    }*/
    println!("{:#?}", pics);

    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/>
    }
}

