// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use futures::executor::block_on;

use axum::{
    Router as AxumRouter,
    routing::get as AxumGetter,
    http::Request as AxumRequest,
    http::Response as AxumResponse,
    body::{ Body as AxumBody, to_bytes },
    http::{StatusCode, Uri},
    // extract::Path as AxumPath,
    // body::Bytes as AxumBytes,
    // response::IntoResponse,
};
use tauri::http::ResponseBuilder;
use tower::{Service, ServiceExt};

// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}


async fn test() -> &'static str {
    println!("test method called");
    "Path: /test"
}

async fn root() -> &'static str {
    println!("root method called");
    "Path: /"
}

async fn fallback(uri: Uri) -> (StatusCode, String) {
    println!("fallback method called on uri: {}", uri);
    (StatusCode::NOT_FOUND, format!("No route for {uri}"))
}

async fn build_response(router: &mut AxumRouter<()>, path: &str) -> AxumResponse<AxumBody> {
    let path = path.replace("clego://", "http://0.0.0.0/");
    println!("build_response: path = {:?}", path);

    let request = AxumRequest::builder()
        .method("GET")
        .uri(path)
        .body(AxumBody::empty())
        .unwrap();

    println!("build_response: request = {:#?}", request);

    let response = router
        .as_service()
        .ready()
        .await
        .unwrap()
        .call(request)
        .await
        .unwrap();

    println!("build_response: response = {:?}", response);

    response
}

fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet])
        .register_uri_scheme_protocol("clego", move |_app, request| {
            println!("------ register_uri_scheme_protocol ------");

            let mut router: AxumRouter<_> = AxumRouter::new()
                .route("/test/", AxumGetter(test))
                .route("/", AxumGetter(root))
                .fallback(fallback);
    
            let path = request.uri();
            println!("register_uri_scheme_protocol: path = {:?}", path);
            let future = build_response(&mut router, path);
            let response: AxumResponse<AxumBody> = block_on(future);
            // extract body and headers from response
            let (parts, body) = response.into_parts();

            println!("register_uri_scheme_protocol: body = {:?} ; parts {:?}", body, parts);
            
            // Convert body into a Vec<u8>
            let body_bytes = block_on(to_bytes(body, usize::MAX))?;

            // Build a tauri response from the axum response
            ResponseBuilder::new()
                .status(parts.status.as_u16())
                .mimetype("text/html")
                .body(body_bytes.to_vec())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
