#!/usr/bin/env bash

# ## logrotate()
#
# Strategically rotate a logfile minimizing data loss.
#
# This function uses a copy, tail and truncate strategy.
#
# ### Usage Examples
#
#     root# logrotate /var/log/my_logfile.log
#
logrotate()
{
  local _file="${1:-}"
  if variable_is_nonempty _file
  then
    timestamp_set

    verbose "Tailing the file in a background process into a tail logfile."
    ( tail -n 0 -f "${_file}" > ${file}.$$.log )&

    local _tail_pid=$!

    verbose "Copying the file's contentes into a new timestamped file."
    cp "${_file}" "${_file}.${timestamp}"

    verbose "Truncating the file."
    cp /dev/null ${_file}

    verbose "Signaling the tail background process to stop."
    kill -QUIT ${_tail_pid}

    verbose "Appending the tail logfile to the new timestamped logfile."
    cat "${file}.$$.log" >> "${file}.${timestamp}"

    verbose "Compressing the timestamped file (gzip)"
    gzip -f -9 "${file}.${timestamp}"

    verbose "Removing the tail logfile"
    rm "${file}.$$.log"
  else
    fail "Cannot rotate a log file as no log file was given."
  fi
}

# ## log\_streams()
#
# Log streams to three files:
#   - standard out
#   - standard in
#   - combined (what the user typically sees)
#
# ### Usage Examples
#
#     root# log_streams "make install" prefix make
#     cat make.out.log
#     root#
#     ...
#
# Alternatively,
#
#     root# log_streams "make install" \
#           out /path/to/out.log \
#           err /path/to/err.log \
#           mix /path/to/mix.log # both out & err as they occurred.
#     root# cat /path/to/mix.log
#     ...
#
log_streams()
{
  local _command="${1:-}" _prefix _err _out _mix

  # TODO: allow specification of path, name prefix
  while (( $# > 0 ))
  do
    _token="${1}"
    shift
    case "${token}" in
      prefix)
        _prefix="${1}."
        ;;
      err)
        _stderr="${1}"
        shift
        ;;
      out)
        _stdout="${1}"
        shift
        ;;
      mix)
        _stdmix="${1}"
        shift
        ;;
      *)
        _command="${1}"
        shift
        ;;
    esac
  done

  : \
    "${_stdout="${2:-stdout.log}"}" \
    "${_stderr="${3:-stderr.log}"}" \
    "${_stdmix="${4:-stdmix.log}"}"

  # It's like fireworks~! :)
  {
    {
      ${_command} 2>&1 1>&3 | tee "${_stderr}"
    } 3>&1 1>&2 | tee "${_stdout}"
  } > "${_stdmix}" 2>&1
}

