mod errorsd;
mod informationd;
mod warningsd;
use self::errorsd::*;
use self::informationd::*;
use self::warningsd::*;

macro_rules! error_occurred {
   () => {
       $crate::ERROR_OCCURRED.store(true, Ordering::Relaxed);
   };
}

macro_rules! warning_occurred {
   () => {
       $crate::WARNING_OCCURRED.store(true, Ordering::Relaxed);
   };
}

macro_rules! e0001 {
   ($fmt1:expr, $fmt2:expr, $fmt3:expr) => {{
       error_occurred!();
       error!(
           "{}   Bad character {} ({:#02x}) found in file name {} at offset {}",
           "E0001", $fmt1, $fmt1 as usize, $fmt2, $fmt3
       );
   }};
}

macro_rules! e0002 {
   ($fmt1:expr, $fmt2:expr) => {{
       error_occurred!();
       error!(
           "{}   File {} has bad permissions: {}",
           "E0002", $fmt1, $fmt2
       );
   }};
}

macro_rules! e0003 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   {} is no text file", "E0003", $fmt);
   }};
}

macro_rules! e0004 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   Empty directory {} detected", "E0004", $fmt);
   }};
}

macro_rules! e0005 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   Empty file {} detected", "E0005", $fmt);
   }};
}

macro_rules! e0006 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   Hidden directory {} detected", "E0006", $fmt);
   }};
}

macro_rules! e0006t {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   Hidden directory {} detected in TDS zip archive",
           "E0006", $fmt
       );
   }};
}

macro_rules! e0007 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   Hidden file {} detected", "E0007", $fmt);
   }};
}

macro_rules! e0007t {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   Hidden file {} detected in TDS zip archive",
           "E0007", $fmt
       );
   }};
}

macro_rules! e0008 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   Temporary file {} detected", "E0008", $fmt);
   }};
}

macro_rules! e0008t {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   Temporary file {} detected in TDS zip archive",
           "E0008", $fmt
       );
   }};
}
macro_rules! e0009 {
   () => {{
       error_occurred!();
       error!(
           "{}   One of README/README.md/README.txt must exist",
           "E0009",
       );
   }};
}

macro_rules! e0010 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   {} is a broken symlink", "E0010", $fmt);
   }};
}

macro_rules! e0011 {
   ($fmt1:expr, $fmt2:expr) => {{
       error_occurred!();
       error!(
           "{}   Directory {} has bad permissions: {}",
           "E0011", $fmt1, $fmt2
       );
   }};
}

macro_rules! e0012 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   File {} has CRLF line endings", "E0012", $fmt);
   }};
}

macro_rules! e0013 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   {} is a socket special file", "E0013", $fmt);
   }};
}

macro_rules! e0014 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   {} is a fifo file", "E0014", $fmt);
   }};
}

macro_rules! e0015 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   {} is a block device file", "E0015", $fmt);
   }};
}

macro_rules! e0016 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   {} is a character device file", "E0016", $fmt);
   }};
}

macro_rules! e0017 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   PDF error detected in {}", "E0017", $fmt);
   }};
}

macro_rules! e0018 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   Unwanted directory {} detected", "E0018", $fmt);
   }};
}

macro_rules! e0019 {
   ($fmt1:expr, $fmt2:expr) => {{
       error_occurred!();
       error!("{}   {} generated by {} exists", "E0019", $fmt1, $fmt2);
   }};
}

macro_rules! e0020 {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   Unwanted directory `{}` detected in the top level directory of a TDS archive",
           "E0020", $fmt
       );
   }};
}

macro_rules! e0021 {
   ($fmt1:expr, $fmt2:expr, $fmt3:expr) => {{
       error_occurred!();
       error!(
           "{}   File {} : Error reading in line {}: {}",
           "E0021", $fmt1, $fmt2, $fmt3
       );
   }};
}

macro_rules! e0022 {
   ($fmt1:expr, $fmt2:expr) => {{
       error_occurred!();
       error!("{}   {}: `{}`", "E0022", $fmt1, $fmt2);
   }};
}
macro_rules! e0023 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   {}", "E0023", $fmt);
   }};
}

macro_rules! e0024 {
   ($fmt1:expr, $fmt2:expr) => {{
       error_occurred!();
       error!(
           "{}   The TDS zip archive {} has bad permissions: {}",
           "E0024", $fmt1, $fmt2
       );
   }};
}

macro_rules! e0025 {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   Duplicate names when ignoring letter case for: {}",
           "E0025", $fmt
       );
   }};
}

macro_rules! e0026 {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   {} : file not in TDS or different in TDS and non-install tree",
           "E0026", $fmt
       );
   }};
}

macro_rules! e0027 {
   ($fmt1:expr, $fmt2:expr) => {{
       error_occurred!();
       error!(
           "{}   {}: An I/O error occurred -> {}",
           "E0027", $fmt1, $fmt2
       );
   }};
}

macro_rules! e0028 {
   ($fmt1:expr, $fmt2:expr) => {{
       error_occurred!();
       error!(
           "{}   No directory {} (= package name) found in path {}",
           "E0028", $fmt1, $fmt2
       );
   }};
}

macro_rules! e0029 {
   ($fmt1:expr, $fmt2:expr) => {{
       error_occurred!();
       error!(
           "{}   {}: {} encoding with BOM detected",
           "E0029", $fmt1, $fmt2
       );
   }};
}

macro_rules! e0030 {
   ($fmt1:expr, $fmt2:expr) => {{
       error_occurred!();
       error!(
           "{}   Symlink {} points to {} which is outside of the package directory tree",
           "E0030", $fmt1, $fmt2
       );
   }};
}

macro_rules! e0031 {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   File name {} contains invalid UTF-8 character(s)",
           "E0031", $fmt
       );
   }};
}

macro_rules! e0034 {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   Unwanted file `{}` detected in the top level directory of a TDS archive",
           "E0034", $fmt
       );
   }};
}

macro_rules! e0035 {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   Unwanted TDS archive `{}` detected in package directory tree",
           "E0035", $fmt
       );
   }};
}

macro_rules! e0036 {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   File `{}` not below `source/` or `doc/` top level directory in TDS zip archive",
           "E0036", $fmt
       );
   }};
}

macro_rules! e0037 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   File {} has CR line endings", "E0037", $fmt);
   }};
}

macro_rules! e0038 {
   ($fmt1:expr, $fmt2:expr, $fmt3:expr, $fmt4:expr) => {{
       error_occurred!();
       error!(
           "{}   File {} has inconsistent line endings: CR={}, LF={}, CRLF={}",
           "E0038", $fmt1, $fmt2, $fmt3, $fmt4
       );
   }};
}

macro_rules! e0039 {
   () => {{
       error_occurred!();
       error!("{}   No doc/ directory found", "E0039");
   }};
}

macro_rules! e0040 {
   () => {{
       error_occurred!();
       error!(
           "{}   Too few top level directories in the TDS zip archive",
           "E0040",
       );
   }};
}

macro_rules! e0041 {
   () => {{
       error_occurred!();
       error!("{}   One or more map file found for the package but none of them is in a path starting with fonts/map/dvips", "E0041");
   }};
}

macro_rules! e0042 {
   ($fmt:expr) => {{
       error_occurred!();
       error!(
           "{}   TDS zip archive: duplicate names when ignoring letter case for: {}",
           "E0042", $fmt
       );
   }};
}

macro_rules! e0043 {
   ($fmt:expr) => {{
       error_occurred!();
       error!("{}   Symlink {} found in TDS zip archive", "E0043", $fmt);
   }};
}

macro_rules! w0001 {
   ($fmt:expr) => {{
       warning_occurred!();
       warn!("{}   Archive as package file detected: {}", "W0001", $fmt);
   }};
}

macro_rules! w0002 {
   () => {{
       warning_occurred!();
       warn!("{}   Duplicate files detected", "W0002",);
   }};
}

macro_rules! w0003 {
   ($fmt:expr) => {{
       warning_occurred!();
       warn!(
           "{}   Same named files detected in the package directory tree: {}",
           "W0003", $fmt
       );
   }};
}

macro_rules! w0004 {
   ($fmt1:expr, $fmt2:expr) => {{
       warning_occurred!();
       warn!(
           "{}   {}: {} encoding with BOM detected",
           "W0004", $fmt1, $fmt2
       );
   }};
}

macro_rules! w0005 {
   ($fmt1:expr, $fmt2:expr) => {{
       warning_occurred!();
       warn!(
           "{}   Very large file {} with size {}MiB detected",
           "W0005", $fmt1, $fmt2
       )
   }};
}

macro_rules! w0006 {
   ($fmt1:expr, $fmt2:expr) => {{
       warning_occurred!();
       warn!(
           "{}   Very large file {} with size {}MiB detected in TDS zip archive",
           "W0006", $fmt1, $fmt2
       )
   }};
}

macro_rules! w0007 {
   ($fmt:expr) => {{
       warning_occurred!();
       warn!(
           "{}   Empty directory {} detected in TDS zip archive",
           "W0007", $fmt
       );
   }};
}

macro_rules! w0008 {
   ($fmt:expr) => {{
       warning_occurred!();
       warn!("{}   Windows file {} has Unix line endings", "W0008", $fmt);
   }};
}

macro_rules! w0009 {
   ($fmt1:expr, $fmt2:expr) => {{
       warning_occurred!();
       warn!(
           "{}   Replacing `{} -> {}` with the same from config file",
           "W0009", $fmt1, $fmt2
       )
   }};
}

macro_rules! w0010 {
   ($fmt:expr) => {{
       warning_occurred!();
       warn!("{}   Hardlinks detected with inode={}", "W0010", $fmt,);
   }};
}

macro_rules! w0011 {
   ($fmt1:expr, $fmt2:expr, $fmt3:expr) => {{
       warning_occurred!();
       warn!(
           "{}   {} has an mtime in the future by {} seconds, or {}",
           "W0011", $fmt1, $fmt2, $fmt3
       )
   }};
}

macro_rules! i0002 {
   ($fmt:expr) => {{
       info!(
           "{}   {} {}",
           "I0002", "Checking package files in directory", $fmt
       );
   }};
}

macro_rules! i0003 {
   ($fmt:expr) => {{
       info!("{}   {} {}", "I0003", "Checking TDS zip archive", $fmt);
   }};
}

macro_rules! i0004 {
   ($fmt:expr) => {{
       info!("{}   Correcting line endings for file {}", "I0004", $fmt);
   }};
}

macro_rules! i0005 {
   ($fmt:expr) => {{
       info!("{}   Correcting permissions for {}", "I0005", $fmt);
   }};
}

macro_rules! i0006 {
   () => {{
       info!(
           "{}   Files having one of the following file name endings are regarded as temporary",
           "I0006",
       );
   }};
}

macro_rules! i0007 {
   ($fmt1:expr, $fmt2:expr) => {{
       info!(
           "{}   {}: Successfully corrected wrong line endings to {}",
           "I0007", $fmt1, $fmt2
       );
   }};
}

macro_rules! i0008 {
   ($fmt1:expr) => {{
       info!("{}   Using config file {}", "I0008", $fmt1);
   }};
}

macro_rules! i0009 {
   ($fmt1:expr, $fmt2:expr, $fmt3:expr) => {{
       warn!(
           "{}   Updating entry `{} -> {}` with `{} -> {}` from config file",
           "I0009", $fmt1, $fmt2, $fmt1, $fmt3
       )
   }};
}

pub fn explains(err: &str) {
   let err_upp = err.to_ascii_uppercase();
   match err_upp.as_str() {
       "E0001" => e0001d(),
       "E0002" => e0002d(),
       "E0003" => e0003d(),
       "E0004" => e0004d(),
       "E0005" => e0005d(),
       "E0006" => e0006d(),
       "E0007" => e0007d(),
       "E0008" => e0008d(),
       "E0009" => e0009d(),
       "E0010" => e0010d(),
       "E0011" => e0011d(),
       "E0012" => e0012d(),
       "E0013" => e0013d(),
       "E0014" => e0014d(),
       "E0015" => e0015d(),
       "E0016" => e0016d(),
       "E0017" => e0017d(),
       "E0018" => e0018d(),
       "E0019" => e0019d(),
       "E0020" => e0020d(),
       "E0021" => e0021d(),
       "E0022" => e0022d(),
       "E0023" => e0023d(),
       "E0024" => e0024d(),
       "E0025" => e0025d(),
       "E0026" => e0026d(),
       "E0027" => e0027d(),
       "E0028" => e0028d(),
       "E0029" => e0029d(),
       "E0030" => e0030d(),
       "E0031" => e0031d(),
       "E0034" => e0034d(),
       "E0035" => e0035d(),
       "E0036" => e0036d(),
       "E0037" => e0037d(),
       "E0038" => e0038d(),
       "E0039" => e0039d(),
       "E0040" => e0040d(),
       "E0041" => e0041d(),
       "E0042" => e0042d(),
       "E0043" => e0043d(),

       //        "I0001" => i0001d!(),
       "I0001" => i0001d(),
       "I0002" => i0002d(),
       "I0003" => i0003d(),
       "I0004" => i0004d(),
       "I0005" => i0005d(),
       "I0006" => i0006d(),
       "I0007" => i0007d(),
       "I0008" => i0008d(),
       "I0009" => i0009d(),

       "W0001" => w0001d(),
       "W0002" => w0002d(),
       "W0003" => w0003d(),
       "W0004" => w0004d(),
       "W0005" => w0005d(),
       "W0006" => w0006d(),
       "W0007" => w0007d(),
       "W0008" => w0008d(),
       "W0009" => w0009d(),
       "W0010" => w0010d(),
       "W0011" => w0011d(),

       e => eprintln!(
           "Unknown error code `{}` specified with option -e resp. --explain. Exiting...",
           e
       ),
   }
}

pub fn explains_all() {
   explains("E0001");
   explains("E0002");
   explains("E0003");
   explains("E0004");
   explains("E0005");
   explains("E0006");
   explains("E0007");
   explains("E0008");
   explains("E0009");
   explains("E0010");
   explains("E0011");
   explains("E0012");
   explains("E0013");
   explains("E0014");
   explains("E0015");
   explains("E0016");
   explains("E0017");
   explains("E0018");
   explains("E0019");
   explains("E0020");
   explains("E0021");
   explains("E0022");
   explains("E0023");
   explains("E0024");
   explains("E0025");
   explains("E0026");
   explains("E0027");
   explains("E0028");
   explains("E0029");
   explains("E0030");
   explains("E0031");
   explains("E0034");
   explains("E0035");
   explains("E0036");
   explains("E0037");
   explains("E0038");
   explains("E0039");
   explains("E0040");
   explains("E0041");
   explains("E0042");
   explains("E0043");

   explains("I0001");
   explains("I0002");
   explains("I0003");
   explains("I0004");
   explains("I0005");
   explains("I0006");
   explains("I0007");
   explains("I0008");
   explains("I0009");

   explains("W0001");
   explains("W0002");
   explains("W0003");
   explains("W0004");
   explains("W0005");
   explains("W0006");
   explains("W0007");
   explains("W0008");
   explains("W0009");
   explains("W0010");
   explains("W0011");
}