// Simplified TAR library implementation for MoonBit
// This version focuses on basic functionality with MoonBit-compatible APIs

///|
/// TAR constants
pub const BLOCK_SIZE : Int = 512

///|
pub const HEADER_SIZE : Int = 512

///|
/// File type indicators
pub enum FileType {
  Normal
  Directory
  Symlink
} derive(Eq, Debug)

///|
/// Convert FileType to byte
pub fn FileType::to_byte(self : FileType) -> Int {
  match self {
    Normal => 48 // '0'
    Directory => 53 // '5'
    Symlink => 50 // '2'
  }
}

///|
/// Simple TAR header (simplified version)
pub struct SimpleHeader {
  name : String
  size : Int
  file_type : FileType
} derive(Debug)

///|
/// TAR entry
pub struct TarEntry {
  header : SimpleHeader
  data : String
} derive(Debug)

///|
/// Simple TAR archive
pub struct TarArchive {
  entries : Array[TarEntry]
} derive(Debug)

///|
/// Create a new archive
pub fn TarArchive::new() -> TarArchive {
  { entries: [] }
}

///|
/// Add a file to the archive
pub fn TarArchive::add_file(
  self : TarArchive,
  name : String,
  content : String,
) -> Unit {
  let header = { name, size: content.length(), file_type: Normal }
  let entry = { header, data: content }
  self.entries.push(entry)
}

///|
/// Add a directory to the archive
pub fn TarArchive::add_directory(self : TarArchive, name : String) -> Unit {
  let dir_name = if name.length() > 0 && name[name.length() - 1] == '/' {
    name
  } else {
    name + "/"
  }
  let header = { name: dir_name, size: 0, file_type: Directory }
  let entry = { header, data: "" }
  self.entries.push(entry)
}

///|
/// Add a symbolic link to the archive
pub fn TarArchive::add_symlink(
  self : TarArchive,
  name : String,
  target : String,
) -> Unit {
  let header = { name, size: target.length(), file_type: Symlink }
  let entry = { header, data: target }
  self.entries.push(entry)
}

///|
/// Get all entries
pub fn TarArchive::get_entries(self : TarArchive) -> Array[TarEntry] {
  self.entries
}

///|
/// Find an entry by name
pub fn TarArchive::find_entry(self : TarArchive, name : String) -> TarEntry? {
  let mut i = 0
  while i < self.entries.length() {
    if self.entries[i].header.name == name {
      return Some(self.entries[i])
    }
    i = i + 1
  }
  None
}

///|
/// Get entry count
pub fn TarArchive::count(self : TarArchive) -> Int {
  self.entries.length()
}

///|
/// Check if archive is empty
pub fn TarArchive::is_empty(self : TarArchive) -> Bool {
  self.entries.length() == 0
}

///|
/// List all file names
pub fn TarArchive::list_names(self : TarArchive) -> Array[String] {
  let names = []
  let mut i = 0
  while i < self.entries.length() {
    names.push(self.entries[i].header.name)
    i = i + 1
  }
  names
}

///|
/// Get archive statistics
pub struct ArchiveStats {
  total_entries : Int
  file_count : Int
  directory_count : Int
  symlink_count : Int
  total_size : Int
} derive(Debug)

///|
/// Get statistics about the archive
pub fn TarArchive::get_stats(self : TarArchive) -> ArchiveStats {
  let mut file_count = 0
  let mut directory_count = 0
  let mut symlink_count = 0
  let mut total_size = 0

  let mut i = 0
  while i < self.entries.length() {
    let entry = self.entries[i]
    match entry.header.file_type {
      Normal => {
        file_count = file_count + 1
        total_size = total_size + entry.header.size
      }
      Directory => directory_count = directory_count + 1
      Symlink => {
        symlink_count = symlink_count + 1
        total_size = total_size + entry.header.size
      }
    }
    i = i + 1
  }

  {
    total_entries: self.entries.length(),
    file_count,
    directory_count,
    symlink_count,
    total_size,
  }
}

///|
/// Create archive from array of (name, content) pairs
pub fn create_simple_archive(files : Array[(String, String)]) -> TarArchive {
  let archive = TarArchive::new()
  let mut i = 0
  while i < files.length() {
    let (name, content) = files[i]
    archive.add_file(name, content)
    i = i + 1
  }
  archive
}

///|
/// Extract all files from archive as (name, content) pairs
pub fn extract_simple_archive(archive : TarArchive) -> Array[(String, String)] {
  let files = []
  let mut i = 0
  while i < archive.entries.length() {
    let entry = archive.entries[i]
    if entry.header.file_type == Normal {
      files.push((entry.header.name, entry.data))
    }
    i = i + 1
  }
  files
}

///|
pub impl Show for FileType with output(self, logger) {
  logger.write_string(@debug.render(self.to_repr(), max_depth=2147483647))
}

///|
pub impl Show for SimpleHeader with output(self, logger) {
  logger.write_string(@debug.render(self.to_repr(), max_depth=2147483647))
}

///|
pub impl Show for TarEntry with output(self, logger) {
  logger.write_string(@debug.render(self.to_repr(), max_depth=2147483647))
}

///|
pub impl Show for TarArchive with output(self, logger) {
  logger.write_string(@debug.render(self.to_repr(), max_depth=2147483647))
}

///|
pub impl Show for ArchiveStats with output(self, logger) {
  logger.write_string(@debug.render(self.to_repr(), max_depth=2147483647))
}