//! Terminfo database interface.

use std::collections::HashMap;
use std::env;
use std::error;
use std::fmt;
use std::fs::File;
use std::io::{self, prelude::*, BufReader};
use std::path::Path;

use super::color;
use super::Terminal;

use parm::{expand, Param, Variables};
use parser::compiled::{msys_terminfo, parse};
use searcher::get_dbpath_for_term;

/// A parsed terminfo database entry.
#[allow(unused)]
#[derive(Debug)]
pub(crate) struct TermInfo {
    /// Names for the terminal
    pub(crate) names: Vec<String>,
    /// Map of capability name to boolean value
    pub(crate) bools: HashMap<String, bool>,
    /// Map of capability name to numeric value
    pub(crate) numbers: HashMap<String, u32>,
    /// Map of capability name to raw (unexpanded) string
    pub(crate) strings: HashMap<String, Vec<u8>>,
}

/// A terminfo creation error.
#[derive(Debug)]
pub(crate) enum Error {
    /// TermUnset Indicates that the environment doesn't include enough information to find
    /// the terminfo entry.
    TermUnset,
    /// MalformedTerminfo indicates that parsing the terminfo entry failed.
    MalformedTerminfo(String),
    /// io::Error forwards any io::Errors encountered when finding or reading the terminfo entry.
    IoError(io::Error),
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        use Error::*;
        match self {
            IoError(e) => Some(e),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use Error::*;
        match *self {
            TermUnset => Ok(()),
            MalformedTerminfo(ref e) => e.fmt(f),
            IoError(ref e) => e.fmt(f),
        }
    }
}

impl TermInfo {
    /// Creates a TermInfo based on current environment.
    pub(crate) fn from_env() -> Result<TermInfo, Error> {
        let term = match env::var("TERM") {
            Ok(name) => TermInfo::from_name(&name),
            Err(..) => return Err(Error::TermUnset),
        };

        if term.is_err() && env::var("MSYSCON").map_or(false, |s| "mintty.exe" == s) {
            // msys terminal
            Ok(msys_terminfo())
        } else {
            term
        }
    }

    /// Creates a TermInfo for the named terminal.
    pub(crate) fn from_name(name: &str) -> Result<TermInfo, Error> {
        if cfg!(miri) {
            // Avoid all the work of parsing the terminfo (it's pretty slow under Miri), and just
            // assume that the standard color codes work (like e.g. the 'colored' crate).
            return Ok(TermInfo {
                names: Default::default(),
                bools: Default::default(),
                numbers: Default::default(),
                strings: Default::default(),
            });
        }

        get_dbpath_for_term(name)
            .ok_or_else(|| {
                Error::IoError(io::Error::new(io::ErrorKind::NotFound, "terminfo file not found"))
            })
            .and_then(|p| TermInfo::from_path(&(*p)))
    }

    /// Parse the given TermInfo.
    pub(crate) fn from_path<P: AsRef<Path>>(path: P) -> Result<TermInfo, Error> {
        Self::_from_path(path.as_ref())
    }
    // Keep the metadata small
    fn _from_path(path: &Path) -> Result<TermInfo, Error> {
        let file = File::open(path).map_err(Error::IoError)?;
        let mut reader = BufReader::new(file);
        parse(&mut reader, false).map_err(Error::MalformedTerminfo)
    }
}

pub(crate) mod searcher;

/// TermInfo format parsing.
pub(crate) mod parser {
    //! ncurses-compatible compiled terminfo format parsing (term(5))
    pub(crate) mod compiled;
}
pub(crate) mod parm;

/// A Terminal that knows how many colors it supports, with a reference to its
/// parsed Terminfo database record.
pub(crate) struct TerminfoTerminal<T> {
    num_colors: u32,
    out: T,
    ti: TermInfo,
}

impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
        let color = self.dim_if_necessary(color);
        if cfg!(miri) && color < 8 {
            // The Miri logic for this only works for the most basic 8 colors, which we just assume
            // the terminal will support. (`num_colors` is always 0 in Miri, so higher colors will
            // just fail. But libtest doesn't use any higher colors anyway.)
            return write!(self.out, "\x1B[3{color}m").and(Ok(true));
        }
        if self.num_colors > color {
            return self.apply_cap("setaf", &[Param::Number(color as i32)]);
        }
        Ok(false)
    }

    fn reset(&mut self) -> io::Result<bool> {
        if cfg!(miri) {
            return write!(self.out, "\x1B[0m").and(Ok(true));
        }
        // are there any terminals that have color/attrs and not sgr0?
        // Try falling back to sgr, then op
        let cmd = match ["sgr0", "sgr", "op"].iter().find_map(|cap| self.ti.strings.get(*cap)) {
            Some(op) => match expand(&op, &[], &mut Variables::new()) {
                Ok(cmd) => cmd,
                Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
            },
            None => return Ok(false),
        };
        self.out.write_all(&cmd).and(Ok(true))
    }
}

impl<T: Write + Send> TerminfoTerminal<T> {
    /// Creates a new TerminfoTerminal with the given TermInfo and Write.
    pub(crate) fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal<T> {
        let nc = if terminfo.strings.contains_key("setaf") && terminfo.strings.contains_key("setab")
        {
            terminfo.numbers.get("colors").map_or(0, |&n| n)
        } else {
            0
        };

        TerminfoTerminal { out, ti: terminfo, num_colors: nc }
    }

    /// Creates a new TerminfoTerminal for the current environment with the given Write.
    ///
    /// Returns `None` when the terminfo cannot be found or parsed.
    pub(crate) fn new(out: T) -> Option<TerminfoTerminal<T>> {
        TermInfo::from_env().map(move |ti| TerminfoTerminal::new_with_terminfo(out, ti)).ok()
    }

    fn dim_if_necessary(&self, color: color::Color) -> color::Color {
        if color >= self.num_colors && color >= 8 && color < 16 { color - 8 } else { color }
    }

    fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
        match self.ti.strings.get(cmd) {
            Some(cmd) => match expand(&cmd, params, &mut Variables::new()) {
                Ok(s) => self.out.write_all(&s).and(Ok(true)),
                Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
            },
            None => Ok(false),
        }
    }
}

impl<T: Write> Write for TerminfoTerminal<T> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.out.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.out.flush()
    }
}
