/// Represents possible wallpaper types.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum WallpaperType {
  /// If the wallpaper's name is `tiled.*`, this variant is chosen.
  ///
  /// `Tiled` means that the image is placed at (0, 0) of the screen and then
  /// repeat along both axes until the screen is filled.
  Tiled,
  /// If the wallpaper's name is `background.*`, this variant is chosen.
  ///
  /// `Background` means that the image is placed at the center of the screen
  /// and is scaled down or up to the size of the screen so that it fills the
  /// entire screen.
  Background,
}

impl ToString for WallpaperType {
  /// Returns a string corresponding to `WallpaperType`'s value.
  ///
  /// # Possible return values
  ///
  /// Enum variant | String value
  /// ------------ | --------------
  /// `Tiled`      | `"tiled"`
  /// `Background` | `"background"`
  fn to_string(&self) -> String {
    match self {
      WallpaperType::Tiled => "tiled",
      WallpaperType::Background => "background",
    }
    .to_string()
  }
}

/// Represents possible wallpaper extensions. It is taken from the wallpaper's
/// name.
///
/// # Notes
///
/// This crate does **not** check the real type of the wallpaper, it is simply
/// taken from the theme's wallpaper filename. If you want to be sure that the
/// wallpaper is either a .jpg or a .png file, do it yourself.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum WallpaperExtension {
  /// If the wallpaper's extension is `.png`, this variant is chosen.
  Png,
  /// If the wallpaper's extension is `.jpg`, this variant is chosen.
  Jpg,
}

impl ToString for WallpaperExtension {
  /// Returns a string corresponding to `WallpaperExtension`'s value.
  ///
  /// # Possible return values
  ///
  /// Enum variant | String value
  /// ------------ | ------------
  /// `Png`        | `"png"`
  /// `Jpg`        | `"jpg"`
  ///
  /// # Examples
  ///
  /// ```
  /// use tdesktop_theme::*;
  ///
  /// let wallpaper = Wallpaper {
  ///   wallpaper_type: WallpaperType::Tiled,
  ///   extension: WallpaperExtension::Jpg,
  ///   bytes: b"Pretend it's a wallpaper".to_vec(),
  /// };
  ///
  /// let name = format!(
  ///   "examples/trash/wallpaper.{}",
  ///   wallpaper.extension.to_string(),
  /// );
  ///
  /// // std::fs::write(name, wallpaper.bytes).unwrap();
  /// ```
  fn to_string(&self) -> String {
    match self {
      WallpaperExtension::Png => "png",
      WallpaperExtension::Jpg => "jpg",
    }
    .to_string()
  }
}

/// Represents a theme's wallpaper.
#[derive(Debug, PartialEq, Clone)]
pub struct Wallpaper {
  /// Represents the type of the wallpaper, e.g. `background.*` or `tiled.*`.
  pub wallpaper_type: WallpaperType,
  /// Represents the extension of the wallpaper, e.g. `*.png` or `*.jpg`.
  pub extension: WallpaperExtension,
  /// Holds the wallpaper's original bytes.
  pub bytes: Vec<u8>,
}

impl Wallpaper {
  /// Generates the name of the wallpaper when the theme is zipped.
  ///
  /// # Possible return values
  ///
  /// `wallpaper.wallpaper_type` | `wallpaper.extension` | Return value
  /// -------------------------- | --------------------- | ------------------
  /// `Tiled`                    | `Png`                 | `"tiled.png"`
  /// `Tiled`                    | `Jpg`                 | `"tiled.jpg"`
  /// `Background`               | `Png`                 | `"background.png"`
  /// `Background`               | `Jpg`                 | `"background.jpg"`
  ///
  /// # Examples
  ///
  /// ```
  /// use tdesktop_theme::*;
  ///
  /// let wallpaper = Wallpaper {
  ///   wallpaper_type: WallpaperType::Background,
  ///   extension: WallpaperExtension::Jpg,
  ///   bytes: Vec::new(),
  /// };
  ///
  /// assert_eq!(wallpaper.get_filename(), "background.jpg");
  /// ```
  pub fn get_filename(&self) -> String {
    format!(
      "{name}.{extension}",
      name = self.wallpaper_type.to_string(),
      extension = self.extension.to_string(),
    )
  }
}

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

  #[test]
  fn converts_type_to_string_correctly() {
    assert_eq!(WallpaperType::Tiled.to_string(), "tiled");
    assert_eq!(WallpaperType::Background.to_string(), "background");
  }

  #[test]
  fn converts_extension_to_string_correctly() {
    assert_eq!(WallpaperExtension::Png.to_string(), "png");
    assert_eq!(WallpaperExtension::Jpg.to_string(), "jpg");
  }

  #[test]
  fn generates_correct_filenames() {
    let mut wallpaper = Wallpaper {
      wallpaper_type: WallpaperType::Tiled,
      extension: WallpaperExtension::Png,
      bytes: Vec::new(),
    };

    assert_eq!(wallpaper.get_filename(), "tiled.png");

    wallpaper.wallpaper_type = WallpaperType::Background;
    assert_eq!(wallpaper.get_filename(), "background.png");

    wallpaper.extension = WallpaperExtension::Jpg;
    assert_eq!(wallpaper.get_filename(), "background.jpg");

    wallpaper.wallpaper_type = WallpaperType::Tiled;
    assert_eq!(wallpaper.get_filename(), "tiled.jpg");
  }
}
