use clap::{Parser, Subcommand};
use client_shared::{message::Message, utils::{rx_messages, tx_message}};
use utils::time::time_millis;

#[derive(Parser, Debug)]
#[command(
    version,
    about,
    author,
    long_about = None,
    help_template = "\
{before-help}{name} {version}
{author-with-newline}{about-with-newline}
{usage-heading} {usage}

{all-args}{after-help}
"
)]
struct Args {
    #[arg(
        short = 'H', long = "host",
        id = "HOST",
        default_value = "localhost:13337",
    )]
    host: String,

    #[arg(
        short = 'p', long = "password",
        id = "PASSWORD",
        default_value = "null",
    )]
    password: String,

    #[arg(
        long = "timeout",
        id = "TIMEOUT",
        default_value = "2",
        help = "Time out connection to server after given value in seconds."
    )]
    timeout_sec: u64,

    #[arg(
        short = 'c', long = "channel",
        id = "CHANNEL",
        default_value = "root",
    )]
    channel: String,
    
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand, Debug)]
enum Commands {
    Get {
        #[arg(
            long = "plain",
            help = "Return data in a human-readable format."
        )]
        plaintext: bool,
    },

    Send {
        #[arg(
            short = 'n', long = "name",
            id = "NAME",
            required = true,
            help = "Name of the author of the message."
        )]
        name: String,

        #[arg(
            short = 'd', long = "content",
            id = "CONTENT",
            required = true,
            help = "Message content."
        )]
        content: String,
    }
}

fn main() {
    let args = Args::parse();

    match args.command {
        Commands::Get { plaintext } => {
            let mut messages = rx_messages(&args.host, &args.password, args.timeout_sec)
                .expect("Failed to load messages.");

            messages.sort_by(|a, b| {
                a.time.cmp(&b.time)
            });

            if plaintext {
                todo!();
            } else {
                let mut messages_json = json::JsonValue::new_array();
                for msg in &messages {
                    if msg.channel.to_lowercase() == args.channel.to_lowercase() {
                        messages_json.push(json::object! {
                            sender: *msg.sender,
                            content: *msg.content,
                            channel: *msg.channel,
                            time_s: (msg.time / 1000) as u64,
                        }).expect("Failed to create JSON object.");
                    }
                }

                println!("{}", messages_json.pretty(2));
            }
        },
        Commands::Send { ref name, ref content } => {
            let mut message = Message {
                sender: name.clone(),
                content: content.clone(),
                channel: args.channel.clone(),
                time: time_millis(),
            };

            message.sanitize();

            tx_message(&args.host, &args.password, args.timeout_sec, message)
                .expect("Failed to send message.");
        },
    }
}
