// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

mod commands;
use {
    crate::commands::{CmdHelper, Command, ReplControl},
    anyhow::{format_err, Context as _, Error},
    fidl_fuchsia_power as fpower, fidl_fuchsia_power_test as spower,
    fidl_fuchsia_power_test::BatterySimulatorProxy,
    fuchsia_async as fasync,
    fuchsia_component::client::connect_to_service,
    fuchsia_syslog as syslog,
    futures::{
        channel::mpsc::{channel, SendError},
        Sink, SinkExt, Stream, StreamExt, TryFutureExt,
    },
    pin_utils::pin_mut,
    rustyline::{error::ReadlineError, CompletionType, Config, EditMode, Editor},
    std::{fmt, thread, time::Duration},
};

static LOG_TAG: &str = "battery_simulator";
static PROMPT: &str = "\x1b[34mbattman>\x1b[0m ";

// ParseResult is used to convey the parsed commands input by user
// and display them either as an error or continue executing the commands
enum ParseResult<T> {
    Valid(T),
    Empty,
    Error(String),
}

// BatteryInfo is a wrapper for BatteryInfo so the print fmt could be
// implemented
struct BatteryInfo {
    info: fpower::BatteryInfo,
}

impl fmt::Display for BatteryInfo {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            formatter,
            concat!(
                "Battery Percentage: {:?}\n",
                "Battery Status: {:?}\n",
                "Charge Status: {:?}\n",
                "Level Status: {:?}\n",
                "Charge Source: {:?}\n",
                "Time Remaining: {:?}\n",
            ),
            self.info.level_percent,
            self.info.status,
            self.info.charge_status,
            self.info.level_status,
            self.info.charge_source,
            self.info.time_remaining.as_ref()
        )
    }
}

async fn print_battery_info(service: &BatterySimulatorProxy) -> Result<(), Error> {
    if service.is_simulating().await? {
        let bi = service.get_battery_info().await?;
        println!("{}", BatteryInfo { info: bi });
    } else {
        let battery_manager_server = connect_to_service::<fpower::BatteryManagerMarker>()?;
        let bi = battery_manager_server.get_battery_info().await?;
        println!("{}", BatteryInfo { info: bi });
    }
    Ok(())
}

fn print_set_help_message() {
    println!(concat!(
        "'set' modifies the state of the simulated battery. ",
        "Modifications only take place once disconnected.\n",
        "The usage of set is as follows:\n\n",
        "set <battery_attribute battery_attribute_value>\n\n",
        "The corresponding field and field values is as follows:\n\n",
        "\tBatteryPercentage\n",
        "\t\tAny int value from [1..100]\n",
        "\tChargeSource\n",
        "\t\tUNKNOWN\n",
        "\t\tNONE\n",
        "\t\tAC_ADAPTER\n",
        "\t\tUSB\n",
        "\t\tWIRELESS\n",
        "\tChargeStatus\n",
        "\t\tUNKNOWN\n",
        "\t\tNOT_CHARGING\n",
        "\t\tCHARGING\n",
        "\t\tDISCHARGING\n",
        "\tLevelStatus\n",
        "\t\tUNKNOWN\n",
        "\t\tOK\n",
        "\t\tWARNING\n",
        "\t\tLOW\n",
        "\t\tCRITICAL\n",
        "\tBatteryStatus\n",
        "\t\tUNKOWN\n",
        "\t\tOK\n",
        "\t\tNOT_AVAILABLE\n",
        "\t\tNOT_PRESENT\n",
        "\tTimeRemaining\n",
        "\t\tInt value representing time in seconds\n\n",
        "Examples:\n",
        "set ChargeSource WIRELESS BatteryPercentage 12\n",
        "set ChargeStatus DISCHARGING TimeRemaining 100 BatteryPercentage 2"
    ))
}

fn set_time_remaining(time_remaining: &str, service: &BatterySimulatorProxy) -> Result<(), Error> {
    let time = time_remaining.parse::<u64>()?;
    let duration = Duration::new(time, 0);
    service.set_time_remaining(duration.as_nanos() as i64)?;
    Ok(())
}

fn set_charge_source(charge_source: &str, service: &BatterySimulatorProxy) -> Result<(), Error> {
    let res = match charge_source {
        "UNKNOWN" => fpower::ChargeSource::Unknown,
        "NONE" => fpower::ChargeSource::None,
        "AC_ADAPTER" => fpower::ChargeSource::AcAdapter,
        "USB" => fpower::ChargeSource::Usb,
        "WIRELESS" => fpower::ChargeSource::Wireless,
        _ => {
            println!("{} does not exist as an option for ChargeSource. Type set --help for more information", charge_source);
            return Ok(());
        }
    };
    service.set_charge_source(res)?;
    Ok(())
}

fn set_battery_percentage(
    battery_percentage: &str,
    service: &BatterySimulatorProxy,
) -> Result<(), Error> {
    let percent: f32 = battery_percentage.parse().unwrap();
    if percent < 0.0 || percent > 100.0 {
        println!("Please enter battery percent from 0 to 100");
        return Ok(());
    }
    service.set_battery_percentage(percent)?;
    Ok(())
}

fn set_battery_status(battery_status: &str, service: &BatterySimulatorProxy) -> Result<(), Error> {
    let res = match battery_status {
        "UNKNOWN" => fpower::BatteryStatus::Unknown,
        "OK" => fpower::BatteryStatus::Ok,
        "NOT_AVAILABLE" => fpower::BatteryStatus::NotAvailable,
        "NOT_PRESENT" => fpower::BatteryStatus::NotPresent,
        _ => {
            println!("{} does not exist as an option for BatteryStatus. Type set --help for more information", battery_status);
            return Ok(());
        }
    };
    service.set_battery_status(res)?;
    Ok(())
}

fn set_level_status(level_status: &str, service: &BatterySimulatorProxy) -> Result<(), Error> {
    let res = match level_status {
        "UNKNOWN" => fpower::LevelStatus::Unknown,
        "OK" => fpower::LevelStatus::Ok,
        "WARNING" => fpower::LevelStatus::Warning,
        "LOW" => fpower::LevelStatus::Low,
        "CRITICAL" => fpower::LevelStatus::Critical,
        _ => {
            println!("{} does not exist as an option for LevelStatus. Type set --help for more information", level_status);
            return Ok(());
        }
    };
    service.set_level_status(res)?;
    Ok(())
}

fn set_charge_status(charge_status: &str, service: &BatterySimulatorProxy) -> Result<(), Error> {
    let res = match charge_status {
        "UNKNOWN" => fpower::ChargeStatus::Unknown,
        "NOT_CHARGING" => fpower::ChargeStatus::NotCharging,
        "CHARGING" => fpower::ChargeStatus::Charging,
        "DISCHARGING" => fpower::ChargeStatus::Discharging,
        "FULL" => fpower::ChargeStatus::Full,
        _ => {
            println!("{} does not exist as an option for ChargeStatus. Type set --help for more information", charge_status);
            return Ok(());
        }
    };
    service.set_charge_status(res)?;
    Ok(())
}

// args is the string of arguments provided by the user. The format is as follows
// args: "<Field> <Value> ...". The <Field> is any field of the BatteryInfo and
// <Value> is the fields corresponding value. The "..." signifies the repetition of
// the previous pattern of field and value.
async fn set_all_information(args: String, service: &BatterySimulatorProxy) -> Result<(), Error> {
    if !service.is_simulating().await? {
        println!("Please disconnect before running set. Type <set --help> for more information");
        return Ok(());
    }
    let commands: Vec<&str> = args.split(" ").collect();
    if commands.len() <= 1 || commands[0] == "--help" {
        print_set_help_message();
        return Ok(());
    } else if commands.len() % 2 != 0 {
        println!("Incorrect number of args. Type <set --help> for more information");
        return Ok(());
    }
    for i in (0..).take(commands.len()).step_by(2) {
        let field = commands[i];
        let arg = commands[i + 1];
        let _ = match field {
            "BatteryPercentage" => set_battery_percentage(arg, service)?,
            "BatteryStatus" => set_battery_status(arg, service)?,
            "ChargeStatus" => set_charge_status(arg, service)?,
            "ChargeSource" => set_charge_source(arg, service)?,
            "LevelStatus" => set_level_status(arg, service)?,
            "TimeRemaining" => set_time_remaining(arg, service)?,
            _ => println!("Incorrect Battery Field {}", field),
        };
    }
    Ok(())
}

/// Handle a single raw input command from a user and indicate whether the command should
/// result in continuation or breaking of the read evaluate print loop.
async fn handle_command(
    service: &BatterySimulatorProxy,
    cmd: Command,
    args: Vec<String>,
) -> Result<ReplControl, Error> {
    let args = args.join(" ");
    match cmd {
        Command::Get => print_battery_info(service).await,
        Command::Set => set_all_information(args, service).await,
        Command::Reconnect => service.reconnect_real_battery().map_err(|e| format_err!("{}", e)),
        Command::Disconnect => service.disconnect_real_battery().map_err(|e| format_err!("{}", e)),
        Command::Help => Ok(println!("{}", Command::help_msg().to_string())),
        Command::Exit | Command::Quit => return Ok(ReplControl::Break),
    }?;

    Ok(ReplControl::Continue)
}

/// Parse a single raw input command from a user into the command type and argument lsit
fn parse_command(line: String) -> ParseResult<(Command, Vec<String>)> {
    let components: Vec<_> = line.trim().split_whitespace().collect();
    match components.split_first() {
        Some((raw_cmd, args)) => match raw_cmd.parse() {
            Ok(cmd) => {
                let args = args.into_iter().map(|s| s.to_string()).collect();
                ParseResult::Valid((cmd, args))
            }
            Err(_) => ParseResult::Error(format!("\"{}\" is not a valid command", raw_cmd)),
        },
        None => ParseResult::Empty,
    }
}

// Parses the command passed and if it's a valid command then it would handle what it should do
async fn parse_and_handle_cmd(
    service: &BatterySimulatorProxy,
    line: String,
) -> Result<ReplControl, Error> {
    match parse_command(line) {
        ParseResult::Valid((cmd, args)) => handle_command(service, cmd, args).await,
        ParseResult::Empty => Ok(ReplControl::Continue),
        ParseResult::Error(err) => {
            println!("{}", err);
            Ok(ReplControl::Continue)
        }
    }
}

/// Generates a rustyline `Editor` in a separate thread to manage user input. This input is returned
/// as a `Stream` of lines entered by the user.
///
/// The thread exits and the `Stream` is exhausted when an error occurs on stdin or the user
/// sends a ctrl-c or ctrl-d sequence.
///
/// Because rustyline shares control over output to the screen with other parts of the system, a
/// `Sink` is passed to the caller to send acknowledgements that a command has been processed and
/// that rustyline should handle the next line of input.
fn cmd_stream() -> (impl Stream<Item = String>, impl Sink<(), Error = SendError>) {
    // Editor thread and command processing thread must be synchronized so that output
    // is printed in the correct order.
    let (mut cmd_sender, cmd_receiver) = channel(512);
    let (ack_sender, mut ack_receiver) = channel(512);
    thread::spawn(move || -> Result<(), Error> {
        let mut exec = fasync::Executor::new().context("error creating the readline event loop")?;
        let fut = async {
            let config = Config::builder()
                .auto_add_history(true)
                .history_ignore_space(true)
                .completion_type(CompletionType::List)
                .edit_mode(EditMode::Vi)
                .build();
            let mut rl: Editor<CmdHelper> = Editor::with_config(config);
            // Add tab completion
            let c = CmdHelper::new();
            rl.set_helper(Some(c));
            loop {
                let readline = rl.readline(PROMPT);
                match readline {
                    Ok(line) => {
                        cmd_sender.try_send(line)?;
                    }
                    Err(ReadlineError::Eof) | Err(ReadlineError::Interrupted) => {
                        return Ok(());
                    }
                    Err(e) => {
                        println!("Error: {:?}", e);
                        return Err(e.into());
                    }
                }
                // Wait until processing thread is finished evaluating the last command
                // before running the next loop in the repl
                ack_receiver.next().await;
            }
        };
        exec.run_singlethreaded(fut)
    });
    (cmd_receiver, ack_sender)
}

async fn run_repl(service: BatterySimulatorProxy) -> Result<(), Error> {
    // `cmd_stream` blocks on input in a separate thread and passes commands and acks back to
    // the main thread via async channels.
    let (mut commands, mut acks) = cmd_stream();
    while let Some(cmd) = commands.next().await {
        match parse_and_handle_cmd(&service, cmd).await {
            Ok(ReplControl::Continue) => {}
            Ok(ReplControl::Break) => break,
            Err(e) => println!("Error handling command: {}", e),
        }
        acks.send(()).await?;
    }
    Ok(())
}

#[fasync::run_singlethreaded]
async fn main() -> Result<(), Error> {
    syslog::init_with_tags(&[LOG_TAG]).expect("Can't init logger - batsim main");
    println!("Welcome to the Battery Simulator. Type help and <Enter> to see all the options!");
    let battery_simulator = connect_to_service::<spower::BatterySimulatorMarker>()?;
    let repl = run_repl(battery_simulator)
        .unwrap_or_else(|e| eprintln!("REPL failed unexpectedly {:?}", e));

    // Pins repl value on the stack
    pin_mut!(repl);

    repl.await;

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[fasync::run_singlethreaded(test)]
    async fn test_disconnect() {
        // Connect to service
        let battery_simulator = connect_to_service::<spower::BatterySimulatorMarker>().unwrap();
        // Disconnect battery
        let res = battery_simulator.disconnect_real_battery();
        assert!(res.is_ok(), "Failed to disconnect");
        // Test disconnect
        let res = battery_simulator.is_simulating().await;
        assert_eq!(res.unwrap(), true);
        // Reconnect battery
        let res = battery_simulator.reconnect_real_battery();
        assert!(res.is_ok(), "Failed to reconnect");
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_battery_percentage() {
        // Connect to service
        let battery_simulator = connect_to_service::<spower::BatterySimulatorMarker>().unwrap();
        // Disconnect battery
        let res = battery_simulator.disconnect_real_battery();
        assert!(res.is_ok(), "Failed to disconnect");
        // Set Battery Percentage
        let res = set_battery_percentage("12.0", &battery_simulator);
        assert!(res.is_ok(), "Failed to set battery percentage");
        // Check Battery Percentage
        let battery_info = battery_simulator.get_battery_info().await;
        assert_eq!(battery_info.unwrap().level_percent.unwrap(), 12.0);
        // Reconnect battery
        let res = battery_simulator.reconnect_real_battery();
        assert!(res.is_ok(), "Failed to reconnect");
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_battery_status() {
        // Connect to service
        let battery_simulator = connect_to_service::<spower::BatterySimulatorMarker>().unwrap();
        // Disconnect battery
        let res = battery_simulator.disconnect_real_battery();
        assert!(res.is_ok(), "Failed to disconnect");
        // Set Battery Status
        let res = set_battery_status("OK", &battery_simulator);
        assert!(res.is_ok(), "Failed to set battery status");
        // Check Battery Status
        let battery_info = battery_simulator.get_battery_info().await;
        assert_eq!(battery_info.unwrap().status.unwrap(), fpower::BatteryStatus::Ok);
        // Reconnect battery
        let res = battery_simulator.reconnect_real_battery();
        assert!(res.is_ok(), "Failed to reconnect");
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_charge_status() {
        // Connect to service
        let battery_simulator = connect_to_service::<spower::BatterySimulatorMarker>().unwrap();
        // Disconnect battery
        let res = battery_simulator.disconnect_real_battery();
        assert!(res.is_ok(), "Failed to disconnect");
        // Set Charge Status
        let res = set_charge_status("NOT_CHARGING", &battery_simulator);
        assert!(res.is_ok(), "Failed to set charge status");
        // Check Charge Status
        let battery_info = battery_simulator.get_battery_info().await;
        assert_eq!(battery_info.unwrap().charge_status.unwrap(), fpower::ChargeStatus::NotCharging);
        // Reconnect battery
        let res = battery_simulator.reconnect_real_battery();
        assert!(res.is_ok(), "Failed to reconnect");
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_charge_source() {
        // Connect to service
        let battery_simulator = connect_to_service::<spower::BatterySimulatorMarker>().unwrap();
        // Disconnect battery
        let res = battery_simulator.disconnect_real_battery();
        assert!(res.is_ok(), "Failed to disconnect");
        // Set Charge Status
        let res = set_charge_source("WIRELESS", &battery_simulator);
        assert!(res.is_ok(), "Failed to set charge source");
        // Check Charge Status
        let battery_info = battery_simulator.get_battery_info().await;
        assert_eq!(battery_info.unwrap().charge_source.unwrap(), fpower::ChargeSource::Wireless);
        // Reconnect battery
        let res = battery_simulator.reconnect_real_battery();
        assert!(res.is_ok(), "Failed to reconnect");
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_level_status() {
        // Connect to service
        let battery_simulator = connect_to_service::<spower::BatterySimulatorMarker>().unwrap();
        // Disconnect battery
        let res = battery_simulator.disconnect_real_battery();
        assert!(res.is_ok(), "Failed to disconnect");
        // Set Level Status
        let res = set_level_status("CRITICAL", &battery_simulator);
        assert!(res.is_ok(), "Failed to set charge source");
        // Check Level Status
        let battery_info = battery_simulator.get_battery_info().await;
        assert_eq!(battery_info.unwrap().level_status.unwrap(), fpower::LevelStatus::Critical);
        // Reconnect battery
        let res = battery_simulator.reconnect_real_battery();
        assert!(res.is_ok(), "Failed to reconnect");
    }
}
