use std::process::{Command};
use std::io::{stdin,stdout,Write};
use colored::Colorize;
use url::{Url, ParseError};
use std::fs;

const DEBUG_MODE: bool = false;

// Import other files
mod parse_gemtext;

fn clear_screen() {
    if DEBUG_MODE == false
    {
        println!("clearing");
        Command::new("clear")
            .status()
            .expect("Failed to clear screen");
    }
}

fn fetch_page(url: &Url) {
    let full_url_formatted = format!("{}", url);

    let output = Command::new("gemget")
        .args([full_url_formatted, "-o".to_string(), "/tmp/page".to_string()])
        .output()
        .expect("Failed to execute gemget command");

    // Check if the command was successful
    if ! output.status.success() {
        println!("{}\n{:?}\n", "Failed to fetch page:".red(), output);
    } 
}

fn render_page(url: Url, source: bool) -> Vec<String> {
	clear_screen();
	fetch_page(&url);
	let mut links = Vec::new();
        if let Ok(mut content) = fs::read_to_string::<String>("/tmp/page".to_string()) {
            Command::new("rm")
                .arg("/tmp/page")
                .output()
                .expect("Failed to delete tmp page");
	    let (screen_width, _screen_height) = termion::terminal_size().unwrap();

            if source == true {
                    content += &format!("{}", &"Viewing source code".yellow());
            }
            else {
                (content, links) = parse_gemtext::parse_gemtext(content);
            }

            for _i in 0..screen_width {
                    print!("-"); 
            }
            print!("{}\n", url);
            for _i in 0..screen_width {
                    print!("-"); 
            }
            println!("\n\n{}", content);
            for _i in 0..screen_width {
                    print!("-"); 
            }
            println!();

            // Return links (you can add link parsing logic)
        }
        return links;
}

fn input() -> String{
    let mut s=String::new();
    let _=stdout().flush();
    stdin().read_line(&mut s).expect("Did not enter a correct string");
    if let Some('\n')=s.chars().next_back() {
        s.pop();
    }
    if let Some('\r')=s.chars().next_back() {
        s.pop();
    }
    return s;
}

fn parse_url(user_input: String, previous_url: &Url) -> Result<Url, ParseError> {
	println!("user input: {}",user_input);
	println!("previous url: {:?}",previous_url);
	let to_parse =  if user_input.contains("://")  {
		println!("Contains different scheme or is a path");
		user_input
	}
	else {
		format!("gemini://{}/{}",Url::host_str(previous_url).expect("ivalid").to_string(), user_input)
	};

	println!("Parsing: {}", to_parse);
	if let Ok(mut url) = Url::parse(&to_parse) {
		if url.port() == None {
			let _ = url.set_port(Some(1965));
		}
		println!("{:?}",url);
		println!("{}",url.as_str());
		println!("parsed successfully");
		return Ok(url)
	}
	else {
		return Err(ParseError::InvalidDomainCharacter)
	}

}

fn main() {
	clear_screen();
	println!("Enter a url: ");
	let user_input = input();

	if user_input == "q" || user_input == "quit" || user_input == "exit" {
		std::process::exit(0);
	}
	let mut load_page: bool = true;
	let mut history: Vec<Url> = Vec::new();
	let mut historical_position: usize = 0;
	let mut links: Vec<String> = Vec::new();
	let mut source: bool = false; // Wether to view source of markdown page or rendered version
	if let Ok(mut url) = parse_url(user_input, &Url::parse(&"gemini://geminiprotocol.net").unwrap()) { // Change this and make internal pages ;)
		history.push(url.clone());
		'mainloop: loop {
			if load_page {
				links = render_page(history[historical_position].clone(), source);
				println!("Enter reference number to follow, h for help, or q to quit");
			}
                        url = history[historical_position].clone();
			load_page = false;

			let user_input = input(); 
			if user_input == "q" {
				break 'mainloop;
			}
                        else if user_input == "d" {
                            println!(
                                "load_page: {}\nhistory: {:?}\nhistorical_postition: {}\nlinks: {:?}\nsource: {}",
                                load_page,
                                history,
                                historical_position,
                                links,
                                source
                            );
                        }
			else if user_input == "r" {
				load_page = true;
				continue;
			}
			else if user_input == "s" {
				source = ! source; // Flip the boolean to toggle source mode
				load_page = true;
			}
			else if user_input == "i" {
				let _ = url.set_path("/"); 				
				for _i in historical_position+1..history.len() {
					history.remove(historical_position+1);
				}
				history.push(url.clone());
				historical_position += 1;
				load_page = true;
			}
			else if user_input == "b" {
				if historical_position > 0 {
					historical_position -= 1;
					load_page = true;
				}
				else {
					println!("At start of history");
				}
			}
			else if user_input == "f" {
				if historical_position < history.len()-1 {
					historical_position += 1;
					load_page = true;
				}
				else {
					println!("At end of history");
				}
			}
			else if user_input == "h" {
				println!("Source code: https://git.javalsai.dynv6.net/deadvey/markdown-webbrowser
q: quit
d: debug info
h: help
r: reload
s: view source code of page
i: visit root index of this host eg: root index of gemini://deadvey.com/blog/4.md is just gemini://deadvey.com
b: go back in history
f: go forward in history
ox: print the hyprlink of reference x eg: o5 or o24
[url]: follow the inputed url");
			}
			else if user_input.chars().nth(0).unwrap() == 'o' {
			    let number_str = &user_input[1..];
			    if let Ok(number) =  number_str.parse::<usize>() {
				println!("{}", links[number]);
			    } else {
				println!("error");
			    }
			}
			else if let Ok(number) = user_input.parse::<usize>() {
				if number < links.len() {
					if let Ok(parsed_value) = parse_url(links[number].clone(), &url.clone()) {
						url = parsed_value;
						for _i in historical_position+1..history.len() {
							history.remove(historical_position+1);
						}
						history.push(url.clone());
						historical_position += 1;
						load_page = true;
					}
					else {
						println!("Invalid url\nAttempting to open url in web browser");
					}
				} else {
					println!("Invalid reference id");
				}
			}
			else if let Ok(parsed_value) = parse_url(user_input, &url.clone()) {
				url = parsed_value;
				for _i in historical_position+1..history.len() {
					history.remove(historical_position+1);
				}
				history.push(url.clone());
				historical_position += 1;
				load_page = true;
			}
			else {
				println!("Invalid input");
			}
		}
	}
	else {
		println!("Invalid mttp url, try mttp:// at the start of your input.");
	}
}

