use crate::args::CLIArgs;
use crate::args::GenHTMLCommandArgs;
use crate::types::File;
use crate::utils::formats::get_format_handler;
use crate::utils::scan_for_music;
use std::cmp::Ordering;
use std::io::Write;

use html_escape::encode_text;

fn table_for_files(files: Vec<File>, includes_path: bool) -> String {
    let mut html_content = String::new();
    let mut path_head = String::new();
    if includes_path {
        path_head.push_str("<th>Path</th>")
    }

    html_content.push_str(
        format!(
            "
        <table class=\"pure-table pure-table-horizontal\">
        <thead>
        <tr>
		{}
        <th>Title</th>
        <th>Artist</th>
        <th>Format</th>
        </tr>
        </thead>
        <tbody>
    ",
            path_head
        )
        .as_str(),
    );

    let mut is_odd = true;
    for file in files.iter() {
        let td_class = match is_odd {
            true => "pure-table-odd",
            false => "pure-table-even",
        };

        let data_title = encode_text(&file.info.tags.title);
        let data_artist = encode_text(&file.info.tags.artist);
        let data_extension = encode_text(&file.extension);

        let mut path_data = String::new();
        if includes_path {
            let file_directory = file.path_from_source.to_string_lossy().to_string();

            path_data.push_str(format!("<td>{}</td>", encode_text(&file_directory)).as_str());
        }
        html_content.push_str(
            format!(
                "
            <tr class=\"{}\">
            {}
            <td>{}</td>
            <td>{}</td>
            <td>{}</td>
            </tr>
        ",
                td_class, path_data, data_title, data_artist, data_extension
            )
            .as_str(),
        );
        is_odd = !is_odd;
    }

    html_content.push_str(
        "
        </tbody>
        </table>
    ",
    );

    html_content
}

pub fn genhtml_command(
    _args: &CLIArgs,
    genhtml_args: &GenHTMLCommandArgs,
) -> Result<(), Box<dyn std::error::Error>> {
    println!("Scanning For Music");
    let mut files = scan_for_music(&genhtml_args.source)?;

    println!("Analysing Files");
    for file in files.iter_mut() {
        println!("Analysing: {:?}", file.join_path_from_source());

        let handler = get_format_handler(file)?;

        file.info = handler.get_audio_file_info(false)?;
    }

    files.sort_by(|a, b| -> Ordering {
        if a.path_from_source != b.path_from_source {
            return a.path_from_source.cmp(&b.path_from_source);
        }

        let a_tags = &a.info.tags;
        let b_tags = &b.info.tags;

        if a_tags.title != b_tags.title {
            return a_tags.title.cmp(&b_tags.title);
        }

        a_tags.artist.cmp(&b_tags.artist)
    });

    let mut html_content = String::new();
    html_content.push_str(
        format!(
            "
		<!DOCTYPE HTML>
		<html>
		<head>
        <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">
		<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">
		<link rel=\"stylesheet\" href=\"https://unpkg.com/purecss@2.0.6/build/pure-min.css\">
		<title>{}</title>
		<meta property=\"og:title\" content=\"{}\" />
		<meta property=\"og:description\" content=\"{}\" />
		</head>
		<body>
	",
            encode_text(&genhtml_args.title),
            encode_text(&genhtml_args.title),
            encode_text(&genhtml_args.description)
        )
        .as_str(),
    );

    html_content.push_str(&table_for_files(files, true));
    html_content.push_str("</body></html>");

    let file_path = std::path::PathBuf::from(genhtml_args.dest.as_str()).join("index.html");
    let html_index_file = std::fs::File::create(file_path);
    match html_index_file {
        Ok(mut file) => match file.write_all(html_content.as_bytes()) {
            Ok(_) => {}
            Err(e) => {
                panic!("Could not write html file: {}", e);
            }
        },
        Err(e) => {
            panic!("Could not create HTML file: {}", e);
        }
    }

    Ok(())
}