#!/bin/bash
#
# File: /usr/local/bin/loadcamerafiles
#
# Mount device (if needed), copy fotos from it to a work-dir,
# rename them by date and time of modification-time,
# delete files on device and unmount it (if needed).
#
#    Copyright (C) 2013  Ingo Kaesmann
#
#    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 2 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, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#
# Script template: 0.3.0
#
# Exit codes:
# 0 = OK
# 1 = Error in parameters
# 2 = Error in configfile, configfile wrong version or not found
# 3 = Library old or not found
# 7 = Files that must not exist, exist
# 8 = Error in other file or other file not found
# 99= Other error
##############################################################################
# SOURCE FILES

. /usr/local/etc/main-inka-sh.conf			# main config
. $LLIBDIR/lib-inka-std.sh				# functions standard
##############################################################################
# DECLARATION OF VARIABLES

# STRINGS
pkgname=inka-loadcamerafiles				# package name to work
lib_inka_std_sh_needed=1.3.6				# standard lib version
conf_file_needed=0.4.0					# conf file version
#----------------------- end of variables to configure -----------------------
version=$(grep "^VERSION" $PROGREG/$pkgname.inf | cut -f 2)	# version
scriptname=$(basename $0)				# name of script
tempfile=$TEMPDIR/$scriptname.$UID.$$.tmp		# temporary file
infolog="logger -p user.info -t $scriptname --"		# log info messages
errlog="logger -p user.err -t $scriptname -- ERROR:"	# log error messages
debuglog="logger -p user.debug -t $scriptname -- DEBUG:" # log debug messages
debug=no						# debug=yes/no
verbose=""						# verbose=""/-q/-v
opt_found=no						# opt_found=yes/no
opt=""							# option
#------------------------- end of standard variables -------------------------
tempfile1=$TEMPDIR/$scriptname.$UI.$$.1.tmp	# another temporary file
list=$scriptname.list				# list of files of device
line=""						# line of list
filenameold=""					# old filename
filenamenew=""					# new filename 
keepchars=""					# chars of filename to keep
last3chars=""					# last character of line
twochars=""					# first 2 chars of file
day=""						# day of mtime of file
month=""					# month of mtime of file
year=""						# year of mtime of file
hour=""						# hour of mtime of file
minute=""					# minute of mtime of file

# NUMBERS
err=0						# exit code
##############################################################################
# FUNCTIONS

function show_help ()
{
# Show help
# Uses: cat
# Return codes: 0

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_help: $# $@" >&2
	#$debuglog show_help: $# $@
fi

cat <<EOT

Aufruf: $scriptname OPTION... GERAET
Laedt Dateien von Kameras (u.a.) auf die Festplatte und benennt sie um.

        -m      Dateisystem des Geraets mounten
        -g      Dateiliste von Geraet holen
        -f      Dateien vom Geraet kopieren
        -r      Dateien umbenennen
        -D      Dateien auf dem Geraet loeschen
        -l      Dateiliste loeschen
        -u      Dateisystem des Geräts unmounten
        -x      -m, -g, -f, -r, -d, -l, -u
 -c GERAET      Konfiguration fuer GERAET anzeigen und beenden
-h, --help      Hilfe anzeigen und beenden
 --version      Versionsinformationen anzeigen und beenden
   --debug      Debug-Modus einschalten
        -q      ohne Erklaerungen und Fehlermeldungen
        -v      mit vielen Erklaerungen der durchgefuehrten Taetigkeiten

GERAET:	Der Name des angeschlossenen Geraets (ohne rc).
Ohne Angabe von GERAET, Auflistung der Geraete-Konfigurationsdateien (GERAETrc)
Es kann nur entweder -c, -m, -g, -f, -r, -D, -l, -u oder -x angegeben werden.
Wenn das Dateinamensformat nicht 'oldstyle' ist, entfaellt -g und -l.
Es wird entweder die Modifikationszeit benutzt, oder die in den Dateinamen
befindlichen Angaben.
EOT
return 0
}
#-----------------------------------------------------------------------------
function show_config ()
{
# Show configuration of program
# Uses: cat, cut, grep
# Return codes: 0

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG show_config: $# $@" >&2
	#$debuglog show_config: $# $@
fi

filenameold=$(echo 1234567890ABCDEFGHIJ | cut -c -${Nrallchars}).$Ext
keepchars=$(echo $filenameold | cut -c ${Nrfirstchar}-${Nrlastchar})
cat <<EOT

Format der Dateinamen auf dem Geraet (z.B. oldstyle): '$Fnametype'
Die Namen der Dateien werden nach folgendem Muster geaendert (wenn oldstyle):
Von $filenameold nach ${Spc0}JJJJ${Spc1}MM${Spc2}TT${Spc3}SS${Spc4}mm${Spc5}${keepchars}${Spc6}.${Ext}
Die Dateien erhalten Namen nach folgendem Muster (wenn nicht oldstyle):
${Spc0}JJJJ${Spc1}MM${Spc2}TT${Spc3}SS${Spc4}mm${Spc5}ss${Spc7}.${Ext}
Mountpunkt ist: '$Mntpt'.
Dateien befinden sich in '$Mntpt/$Filedir'.
Dateien werden im Verzeichnis '$Workdir' gespeichert.
Wird das Geraet vor dem Aufrufen des Programms gemountet? $Automnt
Voreingestelltes Meldungsverhalten ('' = normal, -q = still, -v = viel): '$verbose'

EOT

return 0
}
#-----------------------------------------------------------------------------
function check_workdir ()
{
# Check workdir for existing files of extension type.
# If exist, give mesage and exit.
# Uses: echo, test
# Return codes: 0 = ok, 7 = dir not empty

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG check_workdir: $# $@" >&2
	#$debuglog check_workdir: $# $@
fi

local ret=0

for i in $Workdir/*; do					# workdir is empty?
	test -e $i
	ret=$?						# 0, 1
done
if [ $ret -ne 1 ]; then					# dir is not empty
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - $Workdir ist nicht leer!" >&2
	else
		$errlog "workdir not empty"
	fi
	err=7
fi

return $err
}
#-----------------------------------------------------------------------------
function mount_device ()
{
# Mount device
# Uses: echo, mount
# Return codes: 0 = ok, 99 = error

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG mount_device: $# $@" >&2
	#$debuglog mount_device: $# $@
fi

if [ "$Automnt" == "no" ]; then				# automatic mounting?
	mount $Mntpt
	err=$?
	if [ $err -eq 0 ]; then				# device is mounted
		if [ "$verbose" == "-v" ]; then
			echo "Geraet wurde gemounted."
		fi
	else						# device not mounted
		if [ "$verbose" != "-q" ]; then
			echo "Fehler - Geraet konnte nicht gemountet werden!" >&2
		else
			$errlog "mounting device failed"
		fi
		err=99
	fi
fi

return $err
}
#-----------------------------------------------------------------------------
function get_filelist_oldstyle ()
{
# Get filelist from device
# Uses: cd, echo, ls, rm
# Return codes: 0 = ok, 99 = error

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG get_filelist_oldstyle: $# $@" >&2
	#$debuglog get_filelist_oldstyle: $# $@
fi

cd $Workdir
ls -l --time-style=long-iso $Mntpt/$Filedir/ > $list	# make file-list
err=$?
if [ $err -eq 0 ]; then					# foto-list is ok
	if [ "$verbose" == "-v" ]; then
		echo "Datei '$list' erstellt."
	fi
else							# foto-list is not ok
	rm -f $list
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Datei '$list' konnte nicht erstellt werden!" >&2
	else
		$errlog "creating $list failed"
	fi
	err=99
fi
return $err
}
#-----------------------------------------------------------------------------
function copy_files_oldstyle ()
{
# Copy files from device
# Uses: cd, cp, echo
# Return codes: 0 = 0k, 99 = error

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG copy_files_oldstyle: $# $@" >&2
	#$debuglog copy_files_oldstyle: $# $@
fi

cd $Workdir
if [ "$verbose" != "-q" ]; then
	echo "Bitte warten! Kopiere $Ext-Dateien..."
fi
cp $Mntpt/$Filedir/*.$Ext . 2> /dev/null
err=$?
if [ $err -eq 0 ]; then					# foto-copy is ok
	if [ "$verbose" == "-v" ]; then
		echo "Kopieren von $Ext-Dateien fertig."
	fi
else							# foto-copy is not ok
	if [ "$verbose" != "-q" ]; then
		echo "$Ext-Dateien konnten nicht kopiert werden." >&2
	else
		$errlog "copy $Ext files failed"
	fi
	err=99
fi

return $err
}
#-----------------------------------------------------------------------------
function copy_files_gts7500 ()
{
# Call function for copy files from device
# Uses: copy_files_oldstyle
# Return codes: 0 = ok, 99 = error

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG copy_files_gts7500: $# $@" >&2
	#$debuglog copy_files_gts7500: $# $@
fi

local ret=99

Ext=jpg
copy_files_oldstyle					# copy jpg, if exist
if [ $? -eq 0 ]; then ret=0;fi

Ext=mp4
copy_files_oldstyle					# copy mp4, if exist
if [ $? -eq 0 ]; then ret=0;fi

err=$ret
return $err
}
#-----------------------------------------------------------------------------
function rename_files_oldstyle ()
{
# Change filenames
# Uses: cat, cd, chmod, cut, echo, mv, wc, Read_Lines
# Return codes: 0 = ok, 8 = file not found

local lastline=0 n=0

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG rename_files_oldstyle: $# $@" >&2
	#$debuglog rename_files_oldstyle: $# $@
fi

cd $Workdir
# show new filenames and change filenames from old to new
if [ -e $list ]; then					# foto-list exist
	lastline=$(cat $list | wc -l)
else							# foto-list not exist
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Datei '$list' ist nicht vorhanden!" >&2
		echo "Keine Aenderung von Dateinamen moeglich."
	else
		$errlog "changing filenames failed"
	fi
	return 8
fi
if [ "$verbose" == "-v" ]; then
	echo "Aendere Dateinamen in:"
fi
n=0
while [ $n -lt $lastline ]; do
	let n++
	line=$(Read_Lines $list $n $n)
	last3chars=$(echo $line | cut -d "." -f 2)
	if [ "$last3chars" == "$Ext" ]; then	# line is file to load
		year=$(echo $line | cut -d " " -f 6 | cut -c 1-4)
		month=$(echo $line | cut -d " " -f 6 | cut -c 6-7)
		day=$(echo $line | cut -d " " -f 6 | cut -c 9-10)
		hour=$(echo $line | cut -d " " -f 7 | cut -c 1-2)
		minute=$(echo $line | cut -d " " -f 7 | cut -c 4-5)
		filenameold=$(echo $line | cut -d " " -f 8)
		keepchars=$(echo $filenameold | cut -c ${Nrfirstchar}-${Nrlastchar})
		filenamenew=${Spc0}${year}${Spc1}${month}${Spc2}${day}${Spc3}${hour}${Spc4}${minute}${Spc5}${keepchars}${Spc6}.${Ext}
		if [ "$verbose" == "-v" ]; then
			echo "$filenamenew"
		fi
		mv ./$filenameold $filenamenew	# change filename
		chmod 644 $filenamenew
	fi
done

return 0
}
#-----------------------------------------------------------------------------
function rename_files_gts7500 ()
{
# Change filenames
# Uses: cd, chmod, echo, ls, mmv
# Return codes: 0 = ok, 8 = file not found

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG rename_files_gts7500: $# $@" >&2
	#$debuglog rename_files_gts7500: $# $@
fi

cd $Workdir
if [ "$verbose" == "-v" ]; then
	echo "Aendere Dateinamen in:"
fi
# rename separat jpg files:
mmv "*-*-* *.*.??.jpg" "${Spc0}#1${Spc1}#2${Spc2}#3${Spc3}#4${Spc4}#5${Spc5}#6#7${Spc7}.jpg" > /dev/null 2>&1
# rename serial jpg files:
mmv "*-*-* *.*.*\[*\].jpg" "${Spc0}#1${Spc1}#2${Spc2}#3${Spc3}#4${Spc4}#5${Spc5}#6${Spc6}#7${Spc7}.jpg" > /dev/null 2>&1
# rename mp4 files:
mmv "video-*-*-*-*-*-*.mp4" "${Spc0}#1${Spc1}#2${Spc2}#3${Spc3}#4${Spc4}#5${Spc5}#6${Spc7}.mp4" > /dev/null 2>&1

chmod 644 *
if [ "$verbose" == "-v" ]; then
	/bin/ls $LS_OPTIONS -1
fi

return 0
}
#-----------------------------------------------------------------------------
function delete_files_oldstyle ()
{
# Remove files from device
# Uses: cat, cd, echo, ls, rm, wc
# Return codes: 0 = ok, 99 = error

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG delete_files_oldstyle: $# $@" >&2
	#$debuglog delete_files_oldstyle: $# $@
fi

local nrfwork=0 nrfdevice=0

cd $Workdir
ls *.$Ext > $tempfile 2> /dev/null
nrfwork=$(cat $tempfile | wc -l)			# nr of files in workdir
ls $Mntpt/$Filedir/*.$Ext > $tempfile1 2> /dev/null
nrfdevice=$(cat $tempfile1 | wc -l)			# nr of files on device
if [ $nrfdevice -eq $nrfwork ]; then			# nr of files equal
	if [ "$verbose" == "-v" ]; then
		echo "Loesche $Ext-Dateien im Geraet:"
		cat $tempfile1
	fi
	rm $Mntpt/$Filedir/*.$Ext 2> /dev/null		# remove $Ext files on device, if exist
	if [ $? -ne 0 ] && [ "$verbose" == "-v" ]; then	# no $Ext files on device
		echo "Keine $Ext-Dateien im Geraet vorhanden."
	fi
else							# nr of files unequal
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Anzahl der $Ext-Dateien im Geraet und PC ist unterschiedlich!" >&2
		echo "Dateien im Geraet werden nicht geloescht."
	else
		$errlog "number of $Ext files on device and pc unequal"
	fi
	err=99
fi

rm -f $tempfile $tempfile1
return $err
}
#-----------------------------------------------------------------------------
function delete_files_gts7500 ()
{
# Call function for remove files from device
# Uses: delete_files_oldstyle
# Return codes: 0 = ok, 99 = error

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG delete_files_gts7500: $# $@" >&2
	#$debuglog delete_files_gts7500: $# $@
fi

local ret=8

Ext=jpg
delete_files_oldstyle					# remove files if exist
if [ $? -eq 0 ]; then ret=0;fi

Ext=mp4
delete_files_oldstyle					# remove files if exist
if [ $? -eq 0 ]; then ret=0;fi

return $err
}
#-----------------------------------------------------------------------------
function delete_list_oldstyle ()
{
# Remove filelist from actual directory
# Uses: cd, echo, rm
# Return codes: 0 = ok, 8 = file not found, 99 = other error

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG delete_list_oldstyle: $# $@" >&2
	#$debuglog delete_list_oldstyle: $# $@
fi

cd $Workdir
if [ -e $list ]; then					# foto-list exist
	rm -f $list
	err=$?
	if [ $err -eq 0 ]; then
		if [ "$verbose" == "-v" ]; then
			echo "Datei '$list' geloescht."
		fi
	else
		if [ "$verbose" != "-q" ]; then
			echo "Fehler - '$list' kann nicht geloescht werden." >&2
			echo "Datei bleibt bestehen."
		else
			$errlog "remove $list failed"
		fi
		err=99
	fi
else							# foto-list not exist
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Datei '$list' ist nicht vorhanden!" >&2
		echo "Kein Loeschen moeglich."
	else
		$errlog "file $list not found"
	fi
	err=8
fi

return $err
}
#-----------------------------------------------------------------------------
function unmount_device ()
{
# Unmount device
# Uses: echo, umount
# Return codes: 0 = ok, 99 = error

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG unmount_device: $# $@" >&2
	#$debuglog unmount_device: $# $@
fi

local ret=0

if [ "$Automnt" == "no" ]; then				# automatic mounting?
	umount $Mntpt
	ret=$?
	if [ $ret -eq 0 ]; then				# device is unmounted
		if [ "$verbose" == "-v" ]; then
			echo "Geraet wurde ungemountet."
		fi
	else						# device not mounted
		if [ "$verbose" != "-q" ]; then
			echo "Fehler - Geraet konnte nicht ungemountet werden!" >&2
		else
			$errlog "unmounting device not possible"
		fi
		err=99
		ret=99
	fi
fi

return $ret
}
##############################################################################
# PARSE COMMANDLINE

# Read all options with args and all additional args into variables.
# Stop parsing after last parameter.
# Try to do a check on all parameters and version numbers.
# Handle options -h, -C and -V directly.
# Exit on error.

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG Parse Commandline: $# $@" >&2
	#$debuglog Parse Commandline: $# $@
fi

# get options and options with arguments
while [ "${1:0:1}" == "-" ]; do				# get all options
	case "$1" in
	  -h|--help)	opt=-h;;			# option -h
	  --version)	opt=--v;; 			# option --version
	  --debug)	debug=yes;;			# option --debug
	  -q|--quiet)	verbose=-q;;			# option -q
	  -v|--verbose)	verbose=-v;;			# option -v
#-------------------------- end of standard options --------------------------
	  -c|-m|-g|-f|-r|-D|-l|-u|-x)  opt="$1";;	# opt -c,m,g,g,r,D,l,u.x
	  *)	if [ "$verbose" != "-q" ]; then
			echo "Fehler - Option $1 falsch!" >&2	# error
		else
			$errlog unknown option $1
		fi
		exit 1;;
	esac
	shift
	opt_found=yes
done

# handle standard options -h, --v
case "$opt" in
  -h)	show_help; exit 0;;					# show help
  --v)	echo "$scriptname (${pkgname}) $version"; exit 0;;	# show version
esac

# check library
Compare_Version $lib_inka_std_sh_needed $Lib_Inka_Std_Sh_Version
ret=$?						# (ret: 0,1,2,9,127)
if [ $ret -eq 1 ]; then				# needed lib-version higher than installed
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Programm benoetigt neuere Version von lib-inka-std.sh!" >&2
	else
		$errlog newer version of lib-inka-std.sh needed
	fi
	exit 3
elif [ $ret -eq 9 ] || [ $ret -eq 127 ]; then	# other error (version or lib missing)
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Versionspruefung von lib-inka-std.sh nicht moeglich!"
	else
		$errlog check of version of lib-inka-std.sh impossible
	fi
	exit 3
else						# check ok, reset $ret
	ret=0
fi

# check arguments after options
case "$opt" in
  *)	if [ "$#" -lt 2 ]; then				# parameter count ok
				arg1="$1"		# arg1 = devicename
				shift
	else						# error in param count
			if [ "$verbose" != "-q" ]; then
				echo "Fehler - Parameteranzahl falsch!" >&2
			else
				$errlog parameter count
			fi
			exit 1
	fi;;
esac

# source config file of device if exist, or show existing config files
if [ -e $HOME/.loadcamerafiles/${arg1}rc ]; then	# config file exist
	. $HOME/.loadcamerafiles/${arg1}rc
else							# config file missing
	echo "Es sind folgende Konfigurationsdateien von Geraeten vorhanden:"
	ls $HOME/.loadcamerafiles/*rc | cut -d / -f 5
	exit 1
fi

# check version of config files				# set config var!
#Compare_Version $conf_file_needed $Program_Conf
Compare_Version $conf_file_needed $Loadcamerafiles_Rc
ret=$?						# (ret: 0,1,2,9)
if [ $ret -eq 1 ]; then				# needed config-version higher than installed
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - $scriptname benoetigt neuere Version der Konfig-datei!" >&2
	else
		$errlog newer version of conf file needed
	fi
	exit 2
elif [ $ret -eq 9 ]; then			# other error (version of conffile missing)
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Versionspruefung der Konfig-datei von $scriptname nicht moeglich!"
	else
		$errlog check of version of conf file impossible
	fi
	exit 2
else						# check ok, reset $ret
	ret=0
fi
##############################################################################
# MAINPROGRAM

if [ "$debug" == "yes" ]; then				# debug
	echo "DEBUG Main: $# $@" >&2
	#$debuglog Main: $# $@
fi

verbose="$Verbose"					# verbose=""/-q/-v
#echo "Programm-Sicherung aktiv";exit	### SICHERUNG ###


# Check what to do (initial options and args are removed from cmdline)
case "$opt" in
  -c)	show_config;;
  -m)	mount_device;;
  -g)	if [ "$Fnametype" == "oldstyle" ];then get_filelist_oldstyle;fi;;
  -f)	copy_files_$Fnametype;;
  -r)	rename_files_$Fnametype;;
  -D)	delete_files_$Fnametype;;
  -l)	if [ "$Fnametype" == "oldstyle" ];then delete_list_oldstyle;fi;;
  -u)	unmount_device;;
  -x)
	check_workdir					# check workdir is empty
	if [ $err -eq 0 ];then						# check_workdir ok
		mount_device
		if [ $err -eq 0 ];then						# mount_device ok
			if [ "$Fnametype" == "oldstyle" ];then get_filelist_oldstyle;fi
			if [ $err -eq 0 ];then					# mount_device / get_file_list_oldstyle ok
				copy_files_$Fnametype
				if [ $err -eq 0 ];then				# copy_files ok
					rename_files_$Fnametype
					if [ $err -eq 0 ];then			# rename_files ok
						delete_files_$Fnametype
						if [ $err -eq 0 ];then		# delete_files ok
							if [ "$Fnametype" == "oldstyle" ];then delete_list_oldstyle;fi
						fi
					fi
				fi
			fi
		fi
		unmount_device
	fi;;
  "")							# no opt given
	if [ "$verbose" != "-q" ]; then
		echo "Fehler - Option fehlt!" >&2
	else
		$errlog option missing
	fi
	err=1;;
esac

exit $err
