#!/bin/bash

# Default values
SOURCE_DIR=`pwd`
TARGET_DIR=arcserver:/default/dir
TMP_DIR=~
TODAY=`date +%Y%m%d`
LOG_NAME=$TMP_DIR/archive$TODAY.log
LIST_NAME=$TMP_DIR/archive$TODAY.lst

# Sets source dir from the first parameter or asks user for it
SetSourceDir()
{
    if [[ $# == 0 ]] ; then
	read -p "Source directory [$SOURCE_DIR]: "
	if [[ $REPLY != "" ]] ; then
	    SOURCE_DIR=$REPLY
	fi
    else
	SOURCE_DIR=$1
	echo "Source directory: $SOURCE_DIR"
    fi
}

# Sets target dir from the first parameter or asks user for it
SetTarget()
{
    if [[ $# == 0 ]] ; then
	read -p "Target directory [$TARGET_DIR]: "
	if [[ $REPLY != "" ]] ; then
	    TARGET_DIR=$REPLY
	fi
    else
	TARGET_DIR=$1
	echo "Target directory: $TARGET_DIR"
    fi
}

# Sets reference date from the first parameter or asks user for it
# Calculates number of days between now and the reference date
# 1 optional parameter:
# $1 - reference date, YYYYMMDD (00:00 implied)
# Asks for keyboard input if no parameter specified
# Returns:
# $DAYS - days since the reference date
SetRefDate()
{
    if [[ $# == 0 ]] ; then
	REF_DATE=`date +%Y`0101
        read -p "Archive files older than (YYYYMMDD) [$REF_DATE]: "
	if [[ $REPLY != "" ]] ; then
	    REF_DATE=$REPLY
	fi
    else
	REF_DATE=$1
	echo "Reference date: $REF_DATE"
    fi
    TODAY_SECS=`date +%s`
    REF_SECS=`date +%s -d $REF_DATE`
    SECS=$(($TODAY_SECS - $REF_SECS)) # Works with double parentheses only
    DAYS=$(($SECS/(60*60*24)))
}

# Sets filename prefix from the first parameter or asks user for it
SetPrefix()
{
    if [[ $# == 0 ]] ; then
	echo "The resulting archive filename is prefix$TODAY.tar.gz"
	PREFIX=`basename $SOURCE_DIR`
	read -p "Prefix [$PREFIX]: "
	if [[ $REPLY != "" ]] ; then
	    PREFIX=$REPLY
	fi
    else
	PREFIX=$1
	echo "Filename prefix: $PREFIX"
    fi
}

# Archives the files
# Parameters:
# $1 - the name of the directory to archive
# $2 - prefix to the name of the archive (to be followed by the current date)
# Returns 0 if no errors occurred
ArchiveDir()
{
    #cd $1
    DONE=0
    ARC_NAME=$TMP_DIR/$2$TODAY.tar.gz

    echo "Searching for files older than $DAYS day(s)"
    find $1 -type f -maxdepth 1 -daystart -mtime +$DAYS -print > $LIST_NAME
    if ! [[ -s $LIST_NAME ]] ; then
	echo "No files found"
        return 1
    fi
    echo "Files found: "`wc -l < $LIST_NAME`
    echo "Archiving files to $ARC_NAME"
    tar --create --files-from=$LIST_NAME --preserve-permissions \
	--absolute-names --gzip --file=$ARC_NAME --verbose \
	1>> $LOG_NAME 2>> $LOG_NAME
    EXIT_CODE=$?
    if [[ $EXIT_CODE != 0 ]] ; then
	echo "Error $EXIT_CODE"
	return $EXIT_CODE
    fi
    echo "Done"
    
    echo "Checking the archive against the file system"
    tar --compare --ungzip --file=$ARC_NAME
    EXIT_CODE=$?
    if [[ $EXIT_CODE != 0 ]] ; then
	echo "Error $EXIT_CODE"
	return $EXIT_CODE
    fi
    echo "No errors"
    return 0
}

# Moves the archive file to the target directory
# Parameters:
# $1 - source filename
# $2 - target directory
# Returns 0 if no errors occurred
SecureMove()
{
    echo "Moving $1 to $2"
    scp $1 $2
    if [[ $? != 0 ]] ; then
        return 1
    fi
    rm $1
    if [[ $? != 0 ]] ; then
        return 1
    fi
    echo "Done"
    return 0
}

# Deletes files listed in a filelist ($1 should point to it)
# Returns 0 if no errors occurred
DeleteFiles()
{
    echo "Deleting archived files"
    while read FILE ; do
	rm $FILE
	if [[ $? != 0 ]] ; then
	    return 1
	fi
    done < $1
    echo "Done"
    return 0
}

# Asks user to confirm action
# Accepts 1 parameter:
# $1 - text prompt
# Returns:
# $CHOICE: "YES" or "NO"
Ask()
{
    CHOICE="UNKNOWN"
    
    while [[ $CHOICE == "UNKNOWN" ]]
    do
        read -p "$1" -n 1
        echo
        case $REPLY in
    	    y|Y )	CHOICE="YES"
    		;;
	    n|N )	CHOICE="NO"
        	;;
            *)		echo "Invalid input. Enter y or n. "
		;;
	esac
    done
}

# Main procedure ##############################################################

echo
echo "Starting archive script"
BATCH="NO"
if [[ $# -lt 4 ]] ; then
    echo "Batch usage:"
    echo "archive.sh <source dir> <target dir> <ref date> <filename prefix>"
    echo
    echo "Entering interactive mode"
    echo "Hit Enter to accept [default values]"
else
    # Batch mode means all 4 parameters are supplied and there's nothing to ask
    BATCH="YES"
fi

SetSourceDir $1
SetTarget $2
SetRefDate $3
SetPrefix $4

ArchiveDir $SOURCE_DIR $PREFIX
if [[ $? != 0 ]] ; then
    echo "Could not archive files"
    exit 1
fi

SecureMove $ARC_NAME $TARGET_DIR
if [[ $? != 0 ]] ; then
    echo "Could not move archive file to the target directory"
    exit 1
fi

# In the batch mode, archived files are deleted without confirmation
if [[ $BATCH == "YES" ]] ; then
    CHOICE="YES"
else
    Ask "Delete archived files (y/n)? "
fi
if [[ $CHOICE == "YES" ]] ; then
    DeleteFiles $LIST_NAME
    if [[ $? != 0 ]] ; then
        echo "Could not delete archived files"
        exit 1
    fi
fi

echo "Archiving completed successfully"
echo
exit 0

