#!/bin/bash

# srsync 2.0
# A script using rsync, for synchronization and making backups

# Copyright (C) 2014 Martin de Reuver, <http://www.reuf.nl>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

### Constants ###

# Name of the config file
CONFIG_FILE="srsync.config"

# Exit codes
ERROR_FATAL=1
ERROR_ARG=2
ERROR_CONFIG=3
ERROR_RSYNC=4

### Functions ###

# Check session number (past as an argument to srsync)
function check_session_no()
{
  local error=0
  # Check if argument ($1) is a number > 0 and not empty
  # [1-9] Gives no match for '0', '01', '02' etc. (also no match for '')
  if [ "$1" = "" ]
  then
    echo "$0: no session number given"
    error=1
  elif [[ ! "$1" =~ ^[1-9][0-9]*$ ]]
  then
    echo "$0: invalid session number '$1'"
    error=1
  fi 
  return $error
}

# Check variable count in config file
function check_count()
{
  local error=0
  # Check if count in config file is a number > 0 and not empty
  # [1-9] Gives no match for '0', '01', '02' etc. (also no match for '')
  if [ "$count" = "" ]
  then
    echo "$0: 'count' not found in config file or value is empty"
    error=1
  elif [[ ! "$count" =~ ^[1-9][0-9]*$ ]]
  then
    echo "$0: 'count' in config file has invalid value '$count'"
    error=1
  fi
  return $error
}

# Check variables of a single session in config file
function check_config()
{
  local error=0
  if [ "${name[$1]}" = "" ]
  then
    echo "$0: 'name[$1]' not found in config file or value is empty"
    error=1
  fi
  if [ "${ldir[$1]}" = "" ]
  then
    echo "$0: 'ldir[$1]' not found in config file or value is empty"
    error=1
  fi
  if [ "${rdir[$1]}" = "" ]
  then
    echo "$0: 'rdir[$1]' not found in config file or value is empty"
    error=1
  fi
  if [ "${args[$1]}" = "" ]
  then
    echo "$0: 'args[$1]' not found in config file or value is empty"
    error=1
  fi
  return $error
}

# Check variables of all sessions in config file
function check_config_all()
{
  local error=0
  check_count
  if [ $? -ne 0 ]
  then
    error=1
  else
    for (( i = 1; i <= $count; i++ ))
    do
      check_config $i
      if [ $? -ne 0 ]
      then
        error=1
      fi
    done
  fi
  return $error
}

# Show main menu (a list of all session names)
function show_main_menu()
{
  while :
  do
    # Print menu
    echo ""
    echo "Sync Sessions"
    echo "--------------------"
    for (( i = 1; i <= $count; i++ ))
    do
      echo "$i: ${name[$i]}"
    done
    echo "q: Quit"
    echo "--------------------"
    echo -n "Enter option: "
  
    # Wait for user input: option
    read option
    if [ "$option" = "" ]
    then
      echo "No option entered"
    # User quits
    elif [ "$option" = q ]
    then
      break
    elif [[ ! "$option" =~ ^[1-9][0-9]*$ || $option -gt $count ]]
    then
      echo "Invalid option"
    # Show sync session menu
    else
      show_sub_menu "$option"
    fi
  done
}

# Show session menu (a list of options for a specific session)
function show_sub_menu()
{
  while :
  do
    # Print menu
    echo ""
    echo ${name[$1]}
    echo "--------------------"
    echo "1: Preview"
    echo "2: Synchronize"
    echo "i: Session Info"
    echo "q: Quit"
    echo "--------------------"
    echo -n "Enter option: "
  
    # Wait for user input: option
    read option
    if [ "$option" = "" ]
    then
      echo "No option entered"
    else
      case "$option" in
      1) echo "Preview"
         echo "Source: ${ldir[$1]}"
         echo "Destination: ${rdir[$1]}"
         rsync ${args[$1]} -n "${ldir[$1]}" "${rdir[$1]}"                     
         ;;
      2) echo "Synchronize"
         echo "Source: ${ldir[$1]}"
         echo "Destination: ${rdir[$1]}"
         rsync ${args[$1]} --progress "${ldir[$1]}" "${rdir[$1]}"
         ;;
      i) echo "Session Info"
         echo "Name: ${name[$1]}"
         echo "Source: ${ldir[$1]}"
         echo "Destination: ${rdir[$1]}"
         echo "Rsync options: ${args[$1]}"
         ;;
      q) break
         ;;
      *) echo "Invalid option"
         ;;
      esac
    fi
  done
}

# Directly execute a session
function exec_session()
{
  local error=0
  echo ${name[$1]}
  echo "Synchronize"
  echo "Source: ${ldir[$1]}"
  echo "Destination: ${rdir[$1]}"
  rsync ${args[$1]} --progress "${ldir[$1]}" "${rdir[$1]}"
  if [ $? -ne 0 ]
  then
    error=1
  fi
  return $error
}

function show_help()
{
  echo "Usage: srsync [OPTION [SESSION]]"
  echo ""
  echo "no OPTION    show main menu"
  echo "-s SESSION   show session menu"
  echo "-x SESSION   execute session (synchronize directly)"
  echo "-h           show this help"
  echo "-v           show version and copyright info"
  echo ""
  echo "with SESSION = session number in config file"
}

function show_info()
{
  echo "srsync 2.0"
  echo "A script using rsync, for synchronization and making backups"
  echo ""
  echo "Copyright (C) 2014 Martin de Reuver, <http://www.reuf.nl>"
  echo ""
  echo "This program is free software: you can redistribute it and/or modify"
  echo "it under the terms of the GNU General Public License as published by"
  echo "the Free Software Foundation, either version 3 of the License, or"
  echo "(at your option) any later version."
  echo ""
  echo "This program is distributed in the hope that it will be useful,"
  echo "but WITHOUT ANY WARRANTY; without even the implied warranty of"
  echo "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
  echo "GNU General Public License for more details."
  echo ""
  echo "You should have received a copy of the GNU General Public License"
  echo "along with this program. If not, see <http://www.gnu.org/licenses/>."
}

### Main code ###

# Include config file
. "$CONFIG_FILE"
if [ $? -ne 0 ]
then
  exit $ERROR_FATAL
fi

# Perform action depending on the first argument $1
# Check on errors and exit with the right exit code
case "$1" in
"") # Show main menu
    check_config_all
    if [ $? -ne 0 ]
    then
      exit $ERROR_CONFIG
    fi
    show_main_menu
    ;;
-s) # Show session menu
    # Second argument $2 is session number
    check_session_no $2
    if [ $? -ne 0 ]
    then
      show_help
      exit $ERROR_ARG
    fi
    check_config $2
    if [ $? -ne 0 ]
    then
      exit $ERROR_CONFIG
    fi
    show_sub_menu $2
    ;;
-x) # Execute session
    # Second argument $2 is session number
    check_session_no $2
    if [ $? -ne 0 ]
    then
      show_help
      exit $ERROR_ARG
    fi
    check_config $2
    if [ $? -ne 0 ]
    then
      exit $ERROR_CONFIG
    fi
    exec_session $2
    if [ $? -ne 0 ]
    then
      exit $ERROR_RSYNC
    fi
    ;;
-h) show_help
    ;;
-v) show_info
    ;;
 *) echo "$0: invalid option '$1'"
    show_help
    exit $ERROR_ARG
    ;;
esac
exit 0
