// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Useful modules for OpenTitanTool application development.
pub mod command;
pub mod config;

use crate::io::emu::Emulator;
use crate::io::gpio::{GpioPin, PinMode, PullMode};
use crate::io::i2c::Bus;
use crate::io::spi::Target;
use crate::io::uart::Uart;
use crate::transport::{ProxyOps, Transport, TransportError};
use anyhow::Result;
use std::time::Duration;

use erased_serde::Serialize;
use indicatif::{ProgressBar, ProgressStyle};
use std::any::Any;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

/// Helper function to create a progress bar in the same form for each of
/// the commands which will use it.
pub fn progress_bar(total: u64) -> ProgressBar {
    let progress = ProgressBar::new(total);
    progress.set_style(
        ProgressStyle::default_bar()
            .template("[{elapsed_precise}] [{wide_bar}] {bytes}/{total_bytes} ({eta})"),
    );
    progress
}

#[derive(Default)]
pub struct PinConfiguration {
    /// The input/output mode of the GPIO pin.
    pub mode: Option<PinMode>,
    /// The default/initial level of the pin (true means high).
    pub level: Option<bool>,
    /// Whether the pin has pullup/down resistor enabled.
    pub pull_mode: Option<PullMode>,
}

// This is the structure to be passed to each Command implementation,
// replacing the "bare" Transport argument.  The fields other than
// transport will have been computed from a number ConfigurationFiles.
pub struct TransportWrapper {
    transport: RefCell<Box<dyn Transport>>,
    pin_map: HashMap<String, String>,
    uart_map: HashMap<String, String>,
    spi_map: HashMap<String, String>,
    i2c_map: HashMap<String, String>,
    pin_conf_map: HashMap<String, PinConfiguration>,
    strapping_conf_map: HashMap<String, HashMap<String, PinConfiguration>>,
}

impl TransportWrapper {
    pub fn new(transport: Box<dyn crate::transport::Transport>) -> Self {
        Self {
            transport: RefCell::new(transport),
            pin_map: HashMap::new(),
            uart_map: HashMap::new(),
            spi_map: HashMap::new(),
            i2c_map: HashMap::new(),
            pin_conf_map: HashMap::new(),
            strapping_conf_map: HashMap::new(),
        }
    }

    /// Returns a `Capabilities` object to check the capabilities of this
    /// transport object.
    pub fn capabilities(&self) -> Result<crate::transport::Capabilities> {
        self.transport.borrow().capabilities()
    }

    /// Returns a SPI [`Target`] implementation.
    pub fn spi(&self, name: &str) -> Result<Rc<dyn Target>> {
        self.transport
            .borrow()
            .spi(Self::map_name(&self.spi_map, name).as_str())
    }

    /// Returns a I2C [`Bus`] implementation.
    pub fn i2c(&self, name: &str) -> Result<Rc<dyn Bus>> {
        self.transport
            .borrow()
            .i2c(Self::map_name(&self.i2c_map, name).as_str())
    }

    /// Returns a [`Uart`] implementation.
    pub fn uart(&self, name: &str) -> Result<Rc<dyn Uart>> {
        self.transport
            .borrow()
            .uart(Self::map_name(&self.uart_map, name).as_str())
    }

    /// Returns a [`GpioPin`] implementation.
    pub fn gpio_pin(&self, name: &str) -> Result<Rc<dyn GpioPin>> {
        self.transport
            .borrow()
            .gpio_pin(Self::map_name(&self.pin_map, name).as_str())
    }

    /// Returns a [`Emulator`] implementation.
    pub fn emulator(&self) -> Result<Rc<dyn Emulator>> {
        self.transport.borrow().emulator()
    }

    /// Methods available only on Proxy implementation.
    pub fn proxy_ops(&self) -> Result<Rc<dyn ProxyOps>> {
        self.transport.borrow().proxy_ops()
    }

    /// Invoke non-standard functionality of some Transport implementations.
    pub fn dispatch(&self, action: &dyn Any) -> Result<Option<Box<dyn Serialize>>> {
        self.transport.borrow().dispatch(action)
    }

    /// Given an pin/uart/spi/i2c port name, if the name is a known
    /// alias, return the underlying name/number, otherwise return the
    /// string as is.
    fn map_name(map: &HashMap<String, String>, name: &str) -> String {
        let name = name.to_uppercase();
        // TODO(#8769): Support multi-level aliasing, either by
        // flattening after parsing all files, or by repeated lookup
        // here.
        map.get(&name).cloned().unwrap_or(name)
    }

    /// Apply given configuration to a single pins.
    fn apply_pin_configuration(&self, name: &str, conf: &PinConfiguration) -> Result<()> {
        let pin = self.gpio_pin(name)?;
        if let Some(pin_mode) = conf.mode {
            pin.set_mode(pin_mode)?;
        }
        if let Some(pull_mode) = conf.pull_mode {
            pin.set_pull_mode(pull_mode)?;
        }
        if let Some(level) = conf.level {
            pin.write(level)?;
        }
        Ok(())
    }

    /// Apply given configuration to a all the given pins.
    fn apply_pin_configurations(&self, conf_map: &HashMap<String, PinConfiguration>) -> Result<()> {
        for (name, conf) in conf_map {
            self.apply_pin_configuration(name, conf)?
        }
        Ok(())
    }

    /// Configure all pins as input/output, pullup, etc. as declared in configuration files.
    pub fn apply_default_pin_configurations(&self) -> Result<()> {
        self.apply_pin_configurations(&self.pin_conf_map)
    }

    /// Configure a specific set of pins as strong/weak pullup/pulldown as declared in
    /// configuration files under a given strapping name.
    pub fn apply_pin_strapping(&self, strapping_name: &str) -> Result<()> {
        if let Some(strapping_conf_map) = self.strapping_conf_map.get(strapping_name) {
            self.apply_pin_configurations(&strapping_conf_map)
        } else {
            Err(TransportError::InvalidStrappingName(strapping_name.to_string()).into())
        }
    }

    /// Return the set of pins affected by the given strapping to their "default" (un-strapped)
    /// configuration, that is, to the level declared in the "pins" section of configuration
    /// files, outside of any "strappings" section.
    pub fn remove_pin_strapping(&self, strapping_name: &str) -> Result<()> {
        if let Some(strapping_conf_map) = self.strapping_conf_map.get(strapping_name) {
            for (pin_name, _conf) in strapping_conf_map {
                if let Some(default_pin_conf) = self.pin_conf_map.get(pin_name) {
                    self.apply_pin_configuration(&pin_name, &default_pin_conf)?;
                }
            }
            Ok(())
        } else {
            Err(TransportError::InvalidStrappingName(strapping_name.to_string()).into())
        }
    }

    /// Records the default configuration of a pin, possibly partially overriding previous
    /// configuration.  (E.g. base level configuration files declares a pin as push/pull with a
    /// low level.  A higher level configuration file (which referred to the former in an
    /// include directive) then declares a high level without mentioning input/output/open-drain
    /// mode.  The latter will be processed last, and override just the "level" field, while
    /// leaving the "pin_mode" field unchanged.
    fn record_pin_conf(
        pin_map: &HashMap<String, String>,
        pin_conf_map: &mut HashMap<String, PinConfiguration>,
        pin_conf: &config::PinConfiguration,
    ) {
        if let Some(pin_mode) = pin_conf.mode {
            pin_conf_map
                .entry(Self::map_name(pin_map, &pin_conf.name))
                .or_insert(Default::default())
                .mode = Some(pin_mode);
        }
        if let Some(pull_mode) = pin_conf.pull_mode {
            pin_conf_map
                .entry(Self::map_name(pin_map, &pin_conf.name))
                .or_insert(Default::default())
                .pull_mode = Some(pull_mode);
        }
        if let Some(level) = pin_conf.level {
            pin_conf_map
                .entry(Self::map_name(pin_map, &pin_conf.name))
                .or_insert(Default::default())
                .level = Some(level);
        }
    }

    pub fn add_configuration_file(&mut self, file: config::ConfigurationFile) -> Result<()> {
        // Merge content of configuration file into pin_map and other
        // members.
        for pin_conf in file.pins {
            if let Some(alias_of) = &pin_conf.alias_of {
                self.pin_map
                    .insert(pin_conf.name.to_uppercase(), alias_of.clone());
            }
            // Record default input / open drain / push pull configuration to the pin.
            Self::record_pin_conf(&self.pin_map, &mut self.pin_conf_map, &pin_conf);
        }
        for strapping_conf in file.strappings {
            let mut strapping_pin_map = HashMap::new();
            for pin_conf in strapping_conf.pins {
                Self::record_pin_conf(&self.pin_map, &mut strapping_pin_map, &pin_conf);
            }
            self.strapping_conf_map
                .insert(strapping_conf.name.to_uppercase(), strapping_pin_map);
        }
        for uart_conf in file.uarts {
            if let Some(alias_of) = &uart_conf.alias_of {
                self.uart_map
                    .insert(uart_conf.name.to_uppercase(), alias_of.clone());
            }
            // TODO(#8769): Record baud / parity configration for later
            // use when opening uart.
        }
        Ok(())
    }

    pub fn reset_target(&self, reset_delay: Duration, clear_uart_rx: bool) -> Result<()> {
        log::info!("Asserting the reset signal");
        self.apply_pin_strapping("RESET")?;
        std::thread::sleep(reset_delay);
        if clear_uart_rx {
            log::info!("Clearing the UART RX buffer");
            self.uart("0")?.clear_rx_buffer()?;
        }
        log::info!("Deasserting the reset signal");
        self.remove_pin_strapping("RESET")?;
        std::thread::sleep(reset_delay);
        Ok(())
    }
}
