#!/bin/bash

# Todo: implement --rename

PATH=$PATH:$(dirname "$0")

# Check for required programs before starting 
requiredPrograms=( "cmp" "identify" "basename" "dirname" "rm" "cp" "mv")
requiredOk=1
for prg in "${requiredPrograms[@]}"; do
    path=$(which $prg)
    if [[ "" == "$path" ]]; then
        requiredOk=0
        echo "ERROR: Required program '$prg' not found" >&2
    fi
done

if [[ $requiredOk -eq 0 ]]; then
    echo "       Please provide those programs in order to use this script" >&2
    exit 2
fi

# General help that is shown whenever the script cannot be run because the user
# did not provide sufficient parameters
function showHelp {
    cmd=$(basename "$0")
    echo ""
    echo "        -----===== $cmd =====-----"
    echo ""
    echo "Copies pictures in a given folder into another one ordering them in"
    echo "subfolders named after the image-resolution (e.g. '1280x1024')"
    echo ""
    echo "Obligatory parameters:"
    echo " --indir=      The directory from which to take the images"
    echo "               (It searches in all sub-folders for images)"
    echo " --outdir=     The directory in which to place the ordered Images"
    echo ""
    echo "Optional parameters:"
    echo " --keepSubdirs Creates the original subdir from where the image was"
    echo "               copies as a subdirectory of the outdir"
    echo " --move        Move the images instead of copying them"
    echo " --remDouble   (only with --move) Delete source file if target is the"
    echo "               same"
    echo " --verbose     Output information on every file that is copied/moved"
    echo " --rename      Renames the copied files so that they only contain"
    echo "               the characters a-z,0-9,- and _"
    echo ""
    echo "Example: "
    echo "   \"$cmd --indir=Pictures/Wallpapers --outdir=Pictures/OrderedWallpapers\""
    echo ""
    echo "Exit-Codes:"
    echo "  0 - Everything is fine"
    echo "  1 - Wrong parameters"
    echo "  2 - A target directory could not be created. Script aborted in the middle of work."
    echo "  3 - A file could not be copied. Script aborted in the middle of work."
    echo "  4 - Unknown parameter given"
    echo " 23 - I am watching you."
    echo " 42 - Please state the question."
    echo " 99 - The requested feature is not (yet) implemented"
    echo ""
    
}

# Used to output certain information only in verbose-mode
function echoIfVerbose {
    if [[ $verbose -eq 1 ]]; then
        echo $@
    fi
}

# initializing variables
exitStatus=0
indir=""
outdir=""
keepSubdirs=0
verbose=0
rename=0
move=0
removeDouble=0


# Analyze given parameters
for param in "$@"; do
    knownParam=0

    if [[ "${param:0:8}" == "--indir=" ]]; then
        knownParam=1
        indir="${param:8}"
        # All directories should end with an "/" to prevent problems with the 
        # path later on
        if [[ "/" != ${indir: -1} ]]; then
            indir="$indir/"
        fi
        if [[ ! -d "$indir" ]]; then
            echo "ERROR: No directory ($indir)" >&2
            echo "       Please provide an existing directory as indir parameter" >&2
            indir=""
            exitStatus=1
        fi
    fi

    if [[ "${param:0:9}" == "--outdir=" ]]; then
        knownParam=1
        outdir="${param:9}"
        # All directories should end with an "/" to prevent problems with the 
        # path later on
        if [[ "/" != ${outdir: -1} ]]; then
            outdir="$outdir/"
        fi
        if [[ ! -d "$outdir" ]]; then
            echo "ERROR: No directory ($outdir)" >&2
            echo "       Please provide an existing directory as indir parameter" >&2
            outdir=""
            exitStatus=1
        fi
    fi

    if [[ "${param:0:13}" == "--keepSubdirs" ]]; then
        knownParam=1
        keepSubdirs=1
    fi

    if [[ "${param:0:6}" == "--move" ]]; then
        knownParam=1
        move=1
    fi

    if [[ "${param:0:9}" == "--verbose" ]]; then
        knownParam=1
        verbose=1
    fi
    
    if [[ "${param:0:11}" == "--remDouble" ]]; then
        knownParam=1
        removeDouble=1
    fi

    if [[ "${param:0:8}" == "--rename" ]]; then
        knownParam=1
        rename=1
        echo "ERROR: --rename is currently not implemented!" >&2
        exitStatus=99
    fi



    # Check for unknown parameters
    # Has to be at the end of this loop
    if [[ $knownParam -eq 0 ]]; then
        echo "ERROR: Unknown Parameter '$param'" >&2
        exitStatus=4
    fi
done

if [[ "$indir" == "" || "$outdir" == "" ]]; then
    echo "ERROR: Obligatory Parameters not given" >&2
    echo "       Please provide existing directories as indir and outdir parameters" >&2
    exitStatus=1
fi


if [[ $exitStatus -ne 0 ]]; then
    ## Code for debugging parameters
    #echo "Parameters received:"
    #x=0
    #while [[ "$1" != "" ]]; do
    #   let "x = $x + 1"
    #   echo "$x: $1"
    #   shift
    #done

    showHelp
    exit $exitStatus
fi


# $IFS must be set to newline so a space is not interpreted as separator for
# the files returned by the find-command
IFS=$'\n' 

# Find all files (including 'hidden' .-files)
files=$(find "$indir" -type f)

for filePath in $files; do
    type=$(file -b -i "$filePath" | cut -c 1-5)

    # Check if the file is an image
    if [[ "image" != "$type" ]]; then
        echoIfVerbose "Not an image: '$filePath'"
        continue
    fi

    # Check if the picture is ok
    error=$(identify -regard-warnings "$filePath" 2>&1 >/dev/null)
    status=$?
    if [ $status -ne 0 ]; then
      echo "The image is corrupt or known format: $filePath" >&2
      continue
    fi
    
    # Give Picture Size as "WIDTHxHEIGHT"
    pictureSize=$(identify -format "%wx%h" "$filePath")

    # Get only the filename - without path
    basename=$(basename "$filePath")

    from="$filePath"
    to="$outdir/$pictureSize/$basename"
    # Keep sub directories if this is what the user wishes
    if [[ $keepSubdirs -eq 1 ]]; then
        subPath=${filePath/#"$indir"/""}
        to="$outdir/$pictureSize/$subPath"
    fi

    
    # Check if file already exists
    x=0
    while [[ -f "$to" ]]; do
        cmp -s "$from" "$to"
        status=$?
        # Check if existing file ist the same else rename new file
        if [[ $status -eq 0 ]]; then
            # files are the same
            echoIfVerbose "Picture '$to' already exists and is the same"
            to=""
            
            if [[ $removeDouble -eq 1 ]]; then
                echoIfVerbose "Deleting source file '$from'"
                rm "$from"
            fi
            break
        fi
        
        let "x = $x + 1"
        to="$x-$to"
    done


    # If $to is empty, continues with the next image
    if [[ "$to" == "" ]]; then
        continue
    fi

    
    # Create directories if not already there
    toDir=$(dirname "$to")
    if [[ ! -d "$toDir" ]]; then
        error=$(mkdir -p "$toDir" 2>&1 >/dev/null)
        status=$?
        if [ $status -ne 0 ]; then
            echo "ERROR: Could not create directory: '$toDir'" >&2
            echo "       Please make sure you have sufficient permissions and try again" >&2
            exit 2
        fi
        
    fi
  
    if [[ $move -eq 1 ]]; then
        action="Moving"
        mv "$from" "$to"        
    else
        action="Copying"
        cp "$from" "$to"
    fi
    echoIfVerbose "$action: '$from' --> '$to'"
    
    status=$?
    if [[ $status -ne 0 ]]; then
        echo "ERROR: Could not copy file: '$from' to '$to'" >&2
        echo "       Please make sure you have sufficient permissions and try again" >&2
        exit 3
    fi
    
done










