#!/bin/bash
#
# countdown-status
# Prints how much is left until a specified time.
#
# Author: Jacek Mikrut (jacekmikrut.software at gmail.com)
#
# Copyright (c) 2012 Jacek Mikrut
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

function main() {
  set_default_variable_values

  if requested_help     "$@"; then echo_help;    exit 0; fi
  if requested_version  "$@"; then echo_version; exit 0; fi
  read_script_arguments "$@"

  if data_file_exists; then
    if ! data_file_contains_proper_header; then
      echo_wrong_data_file_header
      exit 1
    fi

    read_data_from_file
    process_data_from_file
  fi

  apply_data_from_script_arguments

  if needs_to_save_data; then
    save_data_to_file
  fi

  echo_status
}

function set_default_variable_values() {
            app_name="countdown-status"
         script_name="countdown-status"
         app_version="0.0.1"
         app_webpage="https://github.com/jacekmikrut/countdown-status"

      data_file_name=".countdown-status-data"
      data_file_path="$HOME/$data_file_name"
    data_file_header="This is a $app_name app's data file. Please do not modify it."

         off_message="OFF"
      prefix_message=""
      suffix_message=""
  time_is_up_message="Time's up!"
}

function requested_help() {
  [[ "$1" == "--help" || "$1" == "help" ]]
}

function requested_version() {
  [[ "$1" == "--version" || "$1" == "-v" ]]
}

function echo_help() {
  echo "Usage: $script_name [-<option> <value> [-<option> <value> [...]]]"
  echo "   or: $script_name --help (to display this information)"
  echo "   or: $script_name --version | -v (to display the version)"
  echo
  echo "Options:"
  echo " -h <hours>     Set number of hours"
  echo " -m <minutes>   Set number of minutes"
  echo " -s <seconds>   Set number of seconds"
  echo " -o <message>   Use custom 'off' message (default: \"$off_message\")"
  echo " -b <message>   Set prefix message (default: \"$prefix_message\")"
  echo " -a <message>   Set suffix message (default: \"$suffix_message\")"
  echo " -u <message>   Set 'time is up' message (default: \"$time_is_up_message\")"
  echo " -f <file-path> Use custom data file (default: \"~/$data_file_name\")"
  echo
  echo "More info at $app_webpage"
}

function echo_version() {
  echo "$app_name version $app_version"
}

function add_remaining_seconds_to_set() {
  if [[ -z ${remaining_seconds_to_set+x} ]]; then remaining_seconds_to_set=0; fi
  ((remaining_seconds_to_set=remaining_seconds_to_set + $1))
}

function read_script_arguments() {
  while getopts ":h:m:s:o:b:a:u:f:" name; do
    case $name in
      h) add_remaining_seconds_to_set $(($OPTARG*60*60));;
      m) add_remaining_seconds_to_set $(($OPTARG*60   ));;
      s) add_remaining_seconds_to_set $(($OPTARG      ));;
      o)                  off_message="$OPTARG";;
      b)        prefix_message_to_set="$OPTARG";;
      a)        suffix_message_to_set="$OPTARG";;
      u)    time_is_up_message_to_set="$OPTARG";;
      f)               data_file_path="$OPTARG";;
    esac
  done
}

function data_file_exists() {
  [[ -e $data_file_path ]]
}

function data_file_contains_proper_header() {
  [[ "`sed -n 1p $data_file_path`" == "$data_file_header" ]]
}

function echo_wrong_data_file_header() {
  echo "The data file ($data_file_path) doesn't contain the proper header. Please select another file path (with -f option)."
}

function read_data_from_file() {
  seconds_from_1970_to_stop_at=`grep -o -P "(?<=^s:)\d+" "$data_file_path"`
                prefix_message=`grep -o -P "(?<=^b:).*"  "$data_file_path"`
                suffix_message=`grep -o -P "(?<=^a:).*"  "$data_file_path"`
            time_is_up_message=`grep -o -P "(?<=^u:).*"  "$data_file_path"`
}

function process_data_from_file() {
  seconds_from_1970_now=`date +%s`
  remaining_seconds=$(($seconds_from_1970_to_stop_at - $seconds_from_1970_now))
}

function apply_data_from_script_arguments() {
  if [[ -n  ${remaining_seconds_to_set+x} ]]; then   remaining_seconds=$remaining_seconds_to_set; fi
  if [[ -n     ${prefix_message_to_set+x} ]]; then         prefix_message=$prefix_message_to_set; fi
  if [[ -n     ${suffix_message_to_set+x} ]]; then         suffix_message=$suffix_message_to_set; fi
  if [[ -n ${time_is_up_message_to_set+x} ]]; then time_is_up_message=$time_is_up_message_to_set; fi
}

function needs_to_save_data() {
  [[ -n  ${remaining_seconds_to_set+x} ]] ||
  [[ -n     ${prefix_message_to_set+x} ]] ||
  [[ -n     ${suffix_message_to_set+x} ]] ||
  [[ -n ${time_is_up_message_to_set+x} ]]
}

function save_data_to_file() {
  data_file_content="$data_file_header"
  data_file_content="$data_file_content\nv:$app_version"
  data_file_content="$data_file_content\ns:`date -d "$remaining_seconds seconds" +%s`"
  data_file_content="$data_file_content\nb:$prefix_message"
  data_file_content="$data_file_content\na:$suffix_message"
  data_file_content="$data_file_content\nu:$time_is_up_message"

  echo -e "$data_file_content" > "$data_file_path"
}

function echo_status() {
  if [[ -z $remaining_seconds ]]; then
    echo "$off_message"

  elif [[ $remaining_seconds -le 0 ]]; then
    echo "$time_is_up_message"

  else
    remaining_hours=$(($remaining_seconds/60/60))
    remaining_minutes_mod_60=$(($remaining_seconds/60%60))
    remaining_seconds_mod_60=$(($remaining_seconds%60))

    echo -n "$prefix_message"

    if [[ $remaining_hours -gt 0 ]]; then
      printf "%d:%02d:%02d" $remaining_hours $remaining_minutes_mod_60 $remaining_seconds_mod_60
    else
      printf "%d:%02d" $remaining_minutes_mod_60 $remaining_seconds_mod_60
    fi

    echo "$suffix_message"
  fi
}

main "$@"