# rename files to strip all special characters.
# usage: name [FILES]
name()
{
  local targets=("${@}") # target file(s).
  local count=0          # processed count.
  local total=${#}       # total to process.

  # all targets except hidden by default.
  if [[ "${targets}" = "" ]]; then
    targets=([^.]*)
    total=${#targets[@]}
  fi

  # process.
  for target in "${targets[@]}"; do
    # increment counter.
    ((count++))

    # parse new name.
    local ext=""
    local name="${target}"

    # ext only for files.
    if [[ -f "${target}" ]]; then
      ext=".${target##*.}"
      name="${target%.*}"
    fi
    
    # Files w/o extension support.
    [[ "${ext#.}" = "${name}" ]] && ext=""

    # Get new name.
    local new_name=$(parse_simplify "${name}")${ext,,}

    # status line.
    local status="[${count}/${total}] ${target} -> ${new_name}"

    # check if same name.
    if [[ "${target}" = "${new_name}" ]]; then
      echo -e "${color_green}${status}: No change.${color_default}"
      continue
    fi

    # check if target name already exists.
    if [[ -f "${new_name}" ]]; then
      echo -e "${color_bred}${status}: already exists!${color_default}"
      return 1
    fi

    # rename target.
    mv -- "${target}" "${new_name}" &> /dev/null

    # show change.
    echo -e "${color_default}${status}${color_default}"
  done
}

# rename all files to their hashes while keeping extensions.
# usage: name_hash [FILES]
name_hash()
{
  local targets=("${@}") # target file(s).
  local count=0          # processed counter.
  local total=${#}       # total to process.

  # all targets except hidden by default.
  if [[ "${targets}" = "" ]]; then
    targets=([^.]*)
    total=${#targets[@]}
  fi

  # process.
  for target in "${targets[@]}"; do
    # process only files.
    if [[ -f "${target}" ]]; then
      # increment count.
      ((count++))

      # extract extension.
      local extension="${target##*.}"
      if [[ "${extension}" = "${target}" ]]; then
        extension=""
      else
        extension=".${extension}"
      fi

      # hash the new name.
      local hash=$(sha1sum -- "${target}" | cut -d\  -f1)
      new_name="${hash,,}${extension,,}"
      
      # prepare status.
      local status="[${count}/${total}] ${target} -> ${new_name}"

      # check if same name.
      if [[ "${target}" = "${new_name}" ]]; then
        echo -e "${color_green}${status}: No change.${color_default}"
        continue
      fi

      # rename target.
      mv -- "${target}" "${new_name}" &> /dev/null

      # show change.
      echo -e "${color_default}${status}${color_default}"
    else
      # Increment count.
      ((count++))

      # Report skip.
      echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}"
    fi
  done
}

# check hashes for renamed files.
# usage: name_hash_check [FILES]
name_hash_check()
{
  local targets=("${@}") # target file(s).
  local total=${#}       # total to process.
  local count=0          # processed counter.
  local failed=0         # failed to process counter.

  # all targets by default.
  if [[ "${targets}" = "" ]]; then
    targets=([^.]*)
    total=${#targets[@]}
  fi

  # process.
  for target in "${targets[@]}"; do
    # process only files.
    if [[ -f "${target}" ]]; then
      # increment count.
      ((count++))

      # status info.
      local status="[${count}/${total}] ${target}"

      # extract hashes.
      local stored="${target%%.*}"
      local actual=$(sha1sum -- "${target}" | cut -d\  -f1)

      # compare hashes.
      if [[ "${stored}" = "${actual}" ]]; then
        echo -e "${color_default}${status}: Validation OK.${color_default}"
      else
        echo -e "${color_bred}${status}: Validation failed.${color_default}"
        ((failed++))
      fi
    else
      # Increment count.
      ((count++))

      # Report skip.
      echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}"
    fi
  done

  # report result.
  if [[ ${count} -gt 1 ]]; then
    if [[ ${failed} -gt 0 ]]; then
      echo -e "${color_bred}Items failed to validate: ${failed}.${color_default}"
    else
      echo -e "${color_green}All successful.${color_default}"
    fi
  fi
}

# rename files for Jellyfin series, i.e. Episode S01E01.mkv
# usage: name_series <SEASON> [FILES]
name_series()
{
  local season="${1}"      # Season number.
  local targets=("${@:2}") # Target files.
  local count=0            # Processed counter.
  local episode=0          # Current episode count.
  local total=${#}         # Total to process.

  # error when no season number specified.
  if [[ "${season}" = "" ]]; then
    echo "usage: name_series <SEASON> [FILES]"
    return 2
  fi

  # all targets by default.
  if [[ "${targets}" = "" ]]; then
    targets=([^.]*)
    total=${#targets[@]}
  fi

  # process.
  for target in "${targets[@]}"; do
    # process only targets.
    if [[ -f "${target}" ]]; then
      # increment episode number.
      ((count++))
      ((episode++))

      # extract new name.
      local new_name="Episode S${season}E$(printf %02d ${episode}).${target##*.}"

      # prepare status.
      local status="[${count}/${total}] ${target} -> ${new_name}"

      # Warning on no change.
      if [[ "${target}" = "${new_name}" ]]; then
        echo -e "${color_green}${status}: No change.${color_default}"
        continue
      fi

      # rename target.
      mv -- "${target}" "${new_name}" &> /dev/null

      # Report status.
      echo -e "${color_default}${status}${color_default}"
    else
      # Increment count.
      ((count++))

      # Report skip.
      echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}"
    fi
  done
}

# rename files for Kavita manga format.
# usage: name_manga <SEASON> [FILES]
name_manga()
{
  local season="${1}"      # Season number.
  local targets=("${@:2}") # Target files.
  local count=0            # Processed counter.
  local episode=0          # Current episode count.
  local total=${#}         # Total to process.
  local manga="${PWD##*/}" # Manga name.

  # error when no season number specified.
  if [[ "${season}" = "" ]]; then
    echo "usage: name_manga <SEASON> [FILES]"
    return 2
  fi

  # all targets by default.
  if [[ "${targets}" = "" ]]; then
    targets=([^.]*)
    total=${#targets[@]}
  fi

  # process.
  for target in "${targets[@]}"; do
    # process only targets.
    if [[ -f "${target}" ]]; then
      # increment episode number.
      ((count++))
      ((episode++))

      # extract new name.
      local new_name="${manga} Vol.${season} Ch.${episode}.${target##*.}"

      # prepare status.
      local status="[${count}/${total}] ${target} -> ${new_name}"

      # Warning on no change.
      if [[ "${target}" = "${new_name}" ]]; then
        echo -e "${color_green}${status}: No change.${color_default}"
        continue
      fi

      # rename target.
      mv -- "${target}" "${new_name}" &> /dev/null

      # Show status.
      echo -e "${color_default}${status}${color_default}"
    else
      # Increment count.
      ((count++))

      # Report skip.
      echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}"
    fi
  done
}

# rename files for new extension.
# usage: name_ext <EXTENSION> [FILES]
name_ext()
{
  local extension="${1}"   # new extension.
  local targets=("${@:2}") # target file(s).
  local count=0            # processed counter.
  local total=$((${#}-1))  # total to process.

  # error when no new extension specified.
  if [[ "${extension}" = "" ]]; then
    echo "usage: name_ext <EXTENSION> [FILES]"
    return 2
  fi

  # all targets by default.
  if [[ "${targets}" = "" ]]; then
    targets=([^.]*)
    total=${#targets[@]}
  fi
  
  # process.
  for target in "${targets[@]}"; do
    # process only targets.
    if [[ -f "${target}" ]]; then
      # increment count.
      ((count++))

      # extract new name.
      local new_name="${target%.*}"."${extension}"

      # Prepare status.
      local status="[${count}/${total}] ${target} -> ${new_name}"

      # Warning on no change.
      if [[ "${target}" = "${new_name}" ]]; then
        echo -e "${color_green}${status}: No change.${color_default}"
        continue
      fi

      # rename target.
      mv -- "${target}" "${new_name}" &> /dev/null

      # show change.
      echo -e "${color_default}${status}${color_default}"
    else
      # Increment count.
      ((count++))

      # Report skip.
      echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}"
    fi
  done
}

# Change file's prefixes.
# Usage: name_prefix [OLD] [NEW] [FILES]
name_prefix()
{
  local old="${1}"         # Old prefix.
  local new="${2}"         # New prefix.
  local targets=("${@:3}") # Target files.
  local count=0            # Total files processed.
  local total=$((${#}-2))  # Total files to process.

  # All targets by default.
  if [[ "${targets}" = "" ]]; then
    targets=([^.]*)
    total=${#targets[@]}
  fi
  
  # Process.
  for target in "${targets[@]}"; do
    # Increment counter.
    ((count++))

    # Create new name.
    local new_name="${new}${target#$old}"

    # Prepare status.
    local status="[${count}/${total}] ${target} -> ${new_name}"

    # Warning on no change.
    if [[ "${target}" = "${new_name}" ]]; then
      echo -e "${color_green}${status}: No change.${color_default}"
      continue
    fi
    
    # Rename.
    mv -- "${target}" "${new_name}" &> /dev/null

    # Show change.
    echo -e "${color_default}${status}${color_default}"
  done
}

# export for parallel.
export -f name name_hash name_hash_check name_ext