# Save file checksums.
# Usage: checksum_create [FILES]
checksum_create()
{
  local IFS=$'\n'
  local targets=("${@}")
  local count=0
  local total=${#}
  local failed=0

  # All files by default.
  if [[ "${targets}" = "" ]]; then
    targets=($(ls --classify | grep -v /\$))
    total=${#targets[@]}
  fi

  # Iterate each file.
  for target in "${targets[@]}"; do
    local hashfile=".${target#./}.sha1"

    # Increment count.
    ((count++))

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

    # Skip if hash exists.
    [[ -f "${hashfile}" ]] && continue

    # Calculate hash.
    pv "${target}" | sha1sum > ${hashfile}

    # Report success.
    if [[ ${?} != 0 ]]; then
      echo -e "${color_bred}${status}: Failed.${color_default}"
      ((failed++))
    fi
  done

  if [[ ${failed} != 0 ]]; then
    echo -e "${color_bred}Failed: ${failed}.${color_default}"
    false
  fi
}

# Check stored values against actual files.
checksum_check()
{
  local IFS=$'\n'
  local targets=("${@}")
  local count=0
  local total=${#}
  local failed=0
  local skipped=0

  # All files by default.
  if [[ "${targets}" = "" ]]; then
    targets=($(ls --classify | grep -v /\$))
    total=${#targets[@]}
  fi

  # Iterate each file.
  for target in "${targets[@]}"; do
    local hashfile=".${target#./}.sha1"

    # Increment count.
    ((count++))

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

    # Skip if hash doesn't exist.
    [[ -f "${hashfile}" ]] || { ((skipped++)); continue; }

    # Calculate hash.
    local stored=$(cat "${hashfile}" | cut -d\  -f1)
    local actual=$(pv "${target}" | sha1sum | cut -d\  -f1)

    if [[ "${stored}" != "${actual}" ]]; then
      echo -e "${color_bred}${status}: Failed.${color_default}"
      ((failed++))
    fi
  done

  if [[ ${skipped} != 0 ]]; then
    echo -e "${color_byellow}Skipped: ${skipped}.${color_default}"
    false
  fi

  if [[ ${failed} != 0 ]]; then
    echo -e "${color_bred}Failed: ${failed}.${color_default}"
    false
  fi
}

checksum()
{
  find -type f | parallel -j $(_core_count) -- sha1sum {} >> checksum.sha1
}

_checksum_create()
{
  local path="${1%/*}"
  local name="${1##*/}"
  sha1sum "${path}/${name}" > "${path}/.${name}.sha1"
}

_checksum_check()
{
  local file="${1##*\ \ }"
  local stored="${1%%\ \ *}"

  # Skip if no file.
  [[ -f "${file}" ]] || return 0

  # Check file hash.
  local actual=$(sha1sum "${file}")
  actual="${actual%%\ \ *}"

  # Compare values.
  if [[ "${stored}" != "${actual}" ]]; then
    echo -e "${color_bred}${file}: Failed.${color_default}"
    return 1
  fi

  return 0
}

export -f checksum_create checksum_check
export -f _checksum_check _checksum_create