//! CSS serialization and source map generation.

use crate::css_modules::CssModule;
use crate::dependencies::{Dependency, DependencyOptions};
use crate::error::{Error, ErrorLocation, PrinterError, PrinterErrorKind};
use crate::rules::{Location, StyleContext};
use crate::selector::SelectorList;
use crate::targets::{Targets, TargetsWithSupportsScope};
use crate::vendor_prefix::VendorPrefix;
use cssparser::{serialize_identifier, serialize_name};
#[cfg(feature = "sourcemap")]
use parcel_sourcemap::{OriginalLocation, SourceMap};

/// Options that control how CSS is serialized to a string.
#[derive(Default)]
pub struct PrinterOptions<'a> {
  /// Whether to minify the CSS, i.e. remove white space.
  pub minify: bool,
  /// An optional reference to a source map to write mappings into.
  #[cfg(feature = "sourcemap")]
  #[cfg_attr(docsrs, doc(cfg(feature = "sourcemap")))]
  pub source_map: Option<&'a mut SourceMap>,
  /// An optional project root path, used to generate relative paths for sources used in CSS module hashes.
  pub project_root: Option<&'a str>,
  /// Targets to output the CSS for.
  pub targets: Targets,
  /// Whether to analyze dependencies (i.e. `@import` and `url()`).
  /// If true, the dependencies are returned as part of the
  /// [ToCssResult](super::stylesheet::ToCssResult).
  ///
  /// When enabled, `@import` and `url()` dependencies
  /// are replaced with hashed placeholders that can be replaced with the final
  /// urls later (after bundling).
  pub analyze_dependencies: Option<DependencyOptions>,
  /// A mapping of pseudo classes to replace with class names that can be applied
  /// from JavaScript. Useful for polyfills, for example.
  pub pseudo_classes: Option<PseudoClasses<'a>>,
}

/// A mapping of user action pseudo classes to replace with class names.
///
/// See [PrinterOptions](PrinterOptions).
#[derive(Default, Debug)]
pub struct PseudoClasses<'a> {
  /// The class name to replace `:hover` with.
  pub hover: Option<&'a str>,
  /// The class name to replace `:active` with.
  pub active: Option<&'a str>,
  /// The class name to replace `:focus` with.
  pub focus: Option<&'a str>,
  /// The class name to replace `:focus-visible` with.
  pub focus_visible: Option<&'a str>,
  /// The class name to replace `:focus-within` with.
  pub focus_within: Option<&'a str>,
}

/// A `Printer` represents a destination to output serialized CSS, as used in
/// the [ToCss](super::traits::ToCss) trait. It can wrap any destination that
/// implements [std::fmt::Write](std::fmt::Write), such as a [String](String).
///
/// A `Printer` keeps track of the current line and column position, and uses
/// this to generate a source map if provided in the options.
///
/// `Printer` also includes helper functions that assist with writing output
/// that respects options such as `minify`, and `css_modules`.
pub struct Printer<'a, 'b, 'c, W> {
  pub(crate) sources: Option<&'c Vec<String>>,
  dest: &'a mut W,
  #[cfg(feature = "sourcemap")]
  #[cfg_attr(docsrs, doc(cfg(feature = "sourcemap")))]
  pub(crate) source_map: Option<&'a mut SourceMap>,
  #[cfg(feature = "sourcemap")]
  #[cfg_attr(docsrs, doc(cfg(feature = "sourcemap")))]
  pub(crate) source_maps: Vec<Option<SourceMap>>,
  pub(crate) loc: Location,
  indent: u8,
  line: u32,
  col: u32,
  pub(crate) minify: bool,
  pub(crate) targets: TargetsWithSupportsScope,
  /// Vendor prefix override. When non-empty, it overrides
  /// the vendor prefix of whatever is being printed.
  pub(crate) vendor_prefix: VendorPrefix,
  pub(crate) in_calc: bool,
  pub(crate) css_module: Option<CssModule<'a, 'b, 'c>>,
  pub(crate) dependencies: Option<Vec<Dependency>>,
  pub(crate) remove_imports: bool,
  pub(crate) pseudo_classes: Option<PseudoClasses<'a>>,
  context: Option<&'a StyleContext<'a, 'b>>,
}

impl<'a, 'b, 'c, W: std::fmt::Write + Sized> Printer<'a, 'b, 'c, W> {
  /// Create a new Printer wrapping the given destination.
  pub fn new(dest: &'a mut W, options: PrinterOptions<'a>) -> Self {
    Printer {
      sources: None,
      dest,
      #[cfg(feature = "sourcemap")]
      source_map: options.source_map,
      #[cfg(feature = "sourcemap")]
      source_maps: Vec::new(),
      loc: Location {
        source_index: 0,
        line: 0,
        column: 1,
      },
      indent: 0,
      line: 0,
      col: 0,
      minify: options.minify,
      targets: TargetsWithSupportsScope::new(options.targets),
      vendor_prefix: VendorPrefix::empty(),
      in_calc: false,
      css_module: None,
      dependencies: if options.analyze_dependencies.is_some() {
        Some(Vec::new())
      } else {
        None
      },
      remove_imports: matches!(&options.analyze_dependencies, Some(d) if d.remove_imports),
      pseudo_classes: options.pseudo_classes,
      context: None,
    }
  }

  /// Returns the current source filename that is being printed.
  pub fn filename(&self) -> &'c str {
    if let Some(sources) = self.sources {
      if let Some(f) = sources.get(self.loc.source_index as usize) {
        f
      } else {
        "unknown.css"
      }
    } else {
      "unknown.css"
    }
  }

  /// Writes a raw string to the underlying destination.
  ///
  /// NOTE: Is is assumed that the string does not contain any newline characters.
  /// If such a string is written, it will break source maps.
  pub fn write_str(&mut self, s: &str) -> Result<(), PrinterError> {
    self.col += s.len() as u32;
    self.dest.write_str(s)?;
    Ok(())
  }

  /// Writes a raw string which may contain newlines to the underlying destination.
  pub fn write_str_with_newlines(&mut self, s: &str) -> Result<(), PrinterError> {
    let mut last_line_start: usize = 0;

    for (idx, n) in s.char_indices() {
      if n == '\n' {
        self.line += 1;
        self.col = 0;

        // Keep track of where the *next* line starts
        last_line_start = idx + 1;
      }
    }

    self.col += (s.len() - last_line_start) as u32;
    self.dest.write_str(s)?;
    Ok(())
  }

  /// Write a single character to the underlying destination.
  pub fn write_char(&mut self, c: char) -> Result<(), PrinterError> {
    if c == '\n' {
      self.line += 1;
      self.col = 0;
    } else {
      self.col += 1;
    }
    self.dest.write_char(c)?;
    Ok(())
  }

  /// Writes a single whitespace character, unless the `minify` option is enabled.
  ///
  /// Use `write_char` instead if you wish to force a space character to be written,
  /// regardless of the `minify` option.
  pub fn whitespace(&mut self) -> Result<(), PrinterError> {
    if self.minify {
      return Ok(());
    }

    self.write_char(' ')
  }

  /// Writes a delimiter character, followed by whitespace (depending on the `minify` option).
  /// If `ws_before` is true, then whitespace is also written before the delimiter.
  pub fn delim(&mut self, delim: char, ws_before: bool) -> Result<(), PrinterError> {
    if ws_before {
      self.whitespace()?;
    }
    self.write_char(delim)?;
    self.whitespace()
  }

  /// Writes a newline character followed by indentation.
  /// If the `minify` option is enabled, then nothing is printed.
  pub fn newline(&mut self) -> Result<(), PrinterError> {
    if self.minify {
      return Ok(());
    }

    self.write_char('\n')?;
    if self.indent > 0 {
      self.write_str(&" ".repeat(self.indent as usize))?;
    }

    Ok(())
  }

  /// Increases the current indent level.
  pub fn indent(&mut self) {
    self.indent += 2;
  }

  /// Decreases the current indent level.
  pub fn dedent(&mut self) {
    self.indent -= 2;
  }

  /// Increases the current indent level by the given number of characters.
  pub fn indent_by(&mut self, amt: u8) {
    self.indent += amt;
  }

  /// Decreases the current indent level by the given number of characters.
  pub fn dedent_by(&mut self, amt: u8) {
    self.indent -= amt;
  }

  /// Returns whether the indent level is greater than one.
  pub fn is_nested(&self) -> bool {
    self.indent > 2
  }

  /// Adds a mapping to the source map, if any.
  #[cfg(feature = "sourcemap")]
  #[cfg_attr(docsrs, doc(cfg(feature = "sourcemap")))]
  pub fn add_mapping(&mut self, loc: Location) {
    self.loc = loc;

    if let Some(map) = &mut self.source_map {
      let mut original = OriginalLocation {
        original_line: loc.line,
        original_column: loc.column - 1,
        source: loc.source_index,
        name: None,
      };

      // Remap using input source map if possible.
      if let Some(Some(sm)) = self.source_maps.get_mut(loc.source_index as usize) {
        let mut found_mapping = false;
        if let Some(mapping) = sm.find_closest_mapping(loc.line, loc.column - 1) {
          if let Some(orig) = mapping.original {
            let sources_len = map.get_sources().len();
            let source_index = map.add_source(sm.get_source(orig.source).unwrap());
            let name = orig.name.map(|name| map.add_name(sm.get_name(name).unwrap()));
            original.original_line = orig.original_line;
            original.original_column = orig.original_column;
            original.source = source_index;
            original.name = name;

            if map.get_sources().len() > sources_len {
              let content = sm.get_source_content(orig.source).unwrap().to_owned();
              let _ = map.set_source_content(source_index as usize, &content);
            }

            found_mapping = true;
          }
        }

        if !found_mapping {
          return;
        }
      }

      map.add_mapping(self.line, self.col, Some(original))
    }
  }

  /// Writes a CSS identifier to the underlying destination, escaping it
  /// as appropriate. If the `css_modules` option was enabled, then a hash
  /// is added, and the mapping is added to the CSS module.
  pub fn write_ident(&mut self, ident: &str, handle_css_module: bool) -> Result<(), PrinterError> {
    if handle_css_module {
      if let Some(css_module) = &mut self.css_module {
        let dest = &mut self.dest;
        let mut first = true;
        css_module.config.pattern.write(
          &css_module.hashes[self.loc.source_index as usize],
          &css_module.sources[self.loc.source_index as usize],
          ident,
          if let Some(content_hashes) = &css_module.content_hashes {
            &content_hashes[self.loc.source_index as usize]
          } else {
            ""
          },
          |s| {
            self.col += s.len() as u32;
            if first {
              first = false;
              serialize_identifier(s, dest)
            } else {
              serialize_name(s, dest)
            }
          },
        )?;

        css_module.add_local(&ident, &ident, self.loc.source_index);
        return Ok(());
      }
    }

    serialize_identifier(ident, self)?;
    Ok(())
  }

  pub(crate) fn write_dashed_ident(&mut self, ident: &str, is_declaration: bool) -> Result<(), PrinterError> {
    self.write_str("--")?;

    match &mut self.css_module {
      Some(css_module) if css_module.config.dashed_idents => {
        let dest = &mut self.dest;
        css_module.config.pattern.write(
          &css_module.hashes[self.loc.source_index as usize],
          &css_module.sources[self.loc.source_index as usize],
          &ident[2..],
          if let Some(content_hashes) = &css_module.content_hashes {
            &content_hashes[self.loc.source_index as usize]
          } else {
            ""
          },
          |s| {
            self.col += s.len() as u32;
            serialize_name(s, dest)
          },
        )?;

        if is_declaration {
          css_module.add_dashed(ident, self.loc.source_index);
        }
      }
      _ => {
        serialize_name(&ident[2..], self)?;
      }
    }

    Ok(())
  }

  /// Returns an error of the given kind at the provided location in the current source file.
  pub fn error(&self, kind: PrinterErrorKind, loc: crate::dependencies::Location) -> Error<PrinterErrorKind> {
    Error {
      kind,
      loc: Some(ErrorLocation {
        filename: self.filename().into(),
        line: loc.line - 1,
        column: loc.column,
      }),
    }
  }

  pub(crate) fn with_context<T, U, F: FnOnce(&mut Printer<'a, 'b, 'c, W>) -> Result<T, U>>(
    &mut self,
    selectors: &SelectorList,
    f: F,
  ) -> Result<T, U> {
    let parent = std::mem::take(&mut self.context);
    let ctx = StyleContext {
      selectors: unsafe { std::mem::transmute(selectors) },
      parent,
    };

    // I can't figure out what lifetime to use here to convince the compiler that
    // the reference doesn't live beyond the function call.
    self.context = Some(unsafe { std::mem::transmute(&ctx) });
    let res = f(self);
    self.context = parent;
    res
  }

  pub(crate) fn with_cleared_context<T, U, F: FnOnce(&mut Printer<'a, 'b, 'c, W>) -> Result<T, U>>(
    &mut self,
    f: F,
  ) -> Result<T, U> {
    let parent = std::mem::take(&mut self.context);
    let res = f(self);
    self.context = parent;
    res
  }

  pub(crate) fn with_parent_context<T, U, F: FnOnce(&mut Printer<'a, 'b, 'c, W>) -> Result<T, U>>(
    &mut self,
    f: F,
  ) -> Result<T, U> {
    let parent = std::mem::take(&mut self.context);
    if let Some(parent) = parent {
      self.context = parent.parent;
    }
    let res = f(self);
    self.context = parent;
    res
  }

  pub(crate) fn context(&self) -> Option<&'a StyleContext<'a, 'b>> {
    self.context.clone()
  }
}

impl<'a, 'b, 'c, W: std::fmt::Write + Sized> std::fmt::Write for Printer<'a, 'b, 'c, W> {
  fn write_str(&mut self, s: &str) -> std::fmt::Result {
    self.col += s.len() as u32;
    self.dest.write_str(s)
  }
}
