// 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 conf;

use crate::io::gpio::GpioPin;
use crate::io::spi::Target;
use crate::io::uart::Uart;

use anyhow::Result;
use erased_serde::Serialize;
use std::any::Any;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

// 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 crate::transport::Transport>>,
    pub pin_map: HashMap<String, String>,
    pub uart_map: HashMap<String, String>,
    pub spi_map: HashMap<String, String>,
    pub flash_map: HashMap<String, conf::FlashConfiguration>,
}

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(),
            flash_map: HashMap::new(),
        }
    }

    /// Returns a `Capabilities` object to check the capabilities of this
    /// transport object.
    pub fn capabilities(&self) -> 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 [`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())
    }

    /// 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 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)
    }

    pub fn add_configuration_file(&mut self, file: conf::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);
            }
            // TODO(#8769): Apply input / open drain / push pull
            // configuration to the pin.
        }
        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);
            }
            // TODO(#8769): Record baud / parity configration for later
            // use when opening uart.
        }
        for flash_conf in file.flash {
            self.flash_map
                .insert(flash_conf.name.clone(), flash_conf.clone());
        }
        Ok(())
    }
}
