#!/bin/sh

# Force bash else run under current shell and hope it can cope - eg *some* busybox
[ -z "${OVS_ENV_JPG:-}" ] && which bash > /dev/null && OVS_ENV_JPG=1 exec bash "$0" "$@"
# $Id:$
#
# run commands to resize a backdrop
# this requires
# libjpeg commands cpeg and djpeg 
# netpbm commands pamscalefixed
#
# Note it requires a lot of cpu esp on embedded machines.
# on NMT it typically requires about 6 seconds per resize operation.
#
# For this reason all covers are processed first, then fanart is done 
# afterwards. 

# --------------------------------------------------------------
# maxthreads determines how many instances of the script run.
# This will fetch and resize images while the main catalog script
# scrapes details.
# for NMT platform use either 1 or 2. 

maxthreads=1


if [ -z "${OVS_HOME:-}" ] ; then
    # Called from catalog.sh/awk so env should already be set.
    EXE=$0
    while [ -h "$EXE" ] ; do EXE="$(readlink "$EXE")"; done
    OVS_HOME="$( cd "$( dirname "$EXE" )"/.. && pwd )"
    . $OVS_HOME/bin/ovsenv
fi

prefix=ovsq.

thread=0



jpg_resize() {

    # resize a jpeg to Sd or Hd backdrop

    input="$1"
    output="$2"

    #This is the initial - approx scale down factor passed to djpeg for performance
    #it is not the final image size.
    #for example we know that going from hd to sd is roughly 1/2 so we first scale by that
    initial_scale="$3"

    local doit=1
    local o=
    local boxset=
    local w=
    local h=
    local width_cmp_fn=

    case "$output" in 

        */_fa/*.sd.jpg) w=685 ; h=460 ; q=90 ;;

        */_fa/*.pal.jpg) w=685 ; h=542 ; q=90 ;; # Pal is created from the SD but we need to maintain the quality

        */_J/*.thumb.jpg) w=$catalog_image_thumb_width ; q=90 ; boxset=1 ;;

        */_A/*.jpg) h=$catalog_image_portrait_height ; q=85 ;; #Actor images are all different sizes. from <100px to 3000 (eg nm0068338). Scale all to 200px

        fanart.jpg|*-fanart.jpg|*/_fa/*.hd.jpg)
            w=$catalog_image_fanart_width ; q=90 ; width_cmp_fn=ne ;; # h=720 this is a standard width at themoviedb - no need to convert those

        */_b/*.jpg)
            w=758 ; q=90 ; width_cmp_fn=ne ;; # this is a standard width at themoviedb - no need to convert those

        poster.jpg|*.jpg|*/_J/*.jpg)
            w=$catalog_image_poster_width ; q=90 ; width_cmp_fn=gt ;; # this is a standard width at themoviedb - no need to convert those

        *) ERROR "Unknown image name [$output]" ; return 1 ;;
    esac
    if [ -n "$w" ] ; then o="-width=$w " ; fi
    if [ -n "$h" ] ; then o="-height=$h " ; fi

    # Check if width is already correct - note tvdb currently serves 1280w fanart and 500 posters s
    if [ -n "$width_cmp_fn" ] ; then
        w2=`jpgwidth "$input"`;
        if [ "$w2" -$width_cmp_fn "$w" ] ; then
            INFO "width=$w2 - required=$w - resizing to $output"
        else
            jpg_size="`sizekb "$input"`"
            if [ "$jpg_size" -lt 1000 ] ; then
                INFO "width ($w2) ok ,  file size ok ${jpg_size}KB - copy to $output"
                doit=0
            else
                INFO "dimensions ok but file size too big ${jpg_size}KB - resizing to $output"
            fi
        fi
    fi

    if [ "$doit" = 0 ] ; then
        if [ "$input" != "$output" ]; then
            cp "$input" "$output"
        fi
    else
        #Could use a pipe but input may = output so use tmp file.
        # We always resize even if the dimensions are unchanged because it makes file size much smaller
        # INFO "$o to $output" 
        # Remove it first in case it was a hard link to the original file.
        tmpjpg=`thread_prefix`.jpg
        tmppnm=`thread_prefix`.pnm

        # we do the usual djpeg | pnmscale | cjpeg  but keep the pnm files so we can reuse them for other sizes.
        # also input and output may be the same so we use intermediate file rather than pipes.
        # this may also give better performance on embedded machines.
        delete_input_pnm=0
        if [ ! -e "$input.pnm" ] ; then
            djpeg -dct fast -scale $initial_scale "$input"  > "$input.pnm" || ERROR "unable to convert $input"
            delete_input_pnm=1
        fi
        if pnmscalefixed $o "$input.pnm" > "$tmppnm" && mv "$tmppnm" "$output.pnm" && \
           cjpeg -dct fast -quality $q "$output.pnm" >  $tmpjpg && rm -f "$output" && mv "$tmpjpg" "$output"  ; then
            perms "$output"
            if [ -n "$boxset" ] ; then
                "$OVS_HOME/bin/add_boxset_icon" "$output" 
            fi
        else
            ERROR "Unable to generate $output from $input using $o"
        fi
        if [ $delete_input_pnm == 1 ] ; then
            rm -f "$input.pnm"
        fi
    fi
}

jpgwidth() {
    rdjpgcom -verbose "$1" | awk '/image is/ { match($0,"[0-9]+w"); print substr($0,RSTART,RLENGTH-1); } '
}


perms() {
    chown $uid:$gid "$@"
}

fetch_resize() {
    calling_pid="$1"; shift;
    type="$1" ; shift; # poster or fanart
    url="$1" ; shift;
    file="$1" ; shift ;

    INFO "Processing : [$type] [$url]"

    case "$url" in
        http*) wget -O "$file" "$@" "$url" && [ -s "$file" ]  ;;
        *) cp "$url" "$file"  ;;
    esac

    if [ $? == 0 ] ; then
        perms "$file"
        case "$OVS_DEPEND_NETPBM_STATUS$OVS_DEPEND_LIBJPEG_STATUS" in
            00) resize_img "$type" "$file" ;;
            *) INFO "No resize - no netpbm" ;;
        esac
    else
        rm -f "$file" 
        ERROR "Failed wget -O $file $@ $url"
    fi
}

sizekb() {
    ls -s "$1" | awk '{print $1}'
}

# $1 = fanart | poster | portrait | banner
# $2 = source file
resize_img() {

    base="${2%.jpg}"
    base="${base%.png}"

    oversight=0;
    case "$base" in
        */Apps/oversight/*) oversight=1 ;;
    esac

    case "$1" in
        fanart)
            if [ $oversight = 1 ] ; then
                jpg_resize "$2" "$base.hd.jpg" "1/1"
                if [ $get_ntsc -eq 1 ] ; then
                    jpg_resize "$base.hd.jpg" "$base.sd.jpg" "1/2"
                fi
                if [ $get_pal -eq 1 ] ; then
                    jpg_resize "$base.hd.jpg" "$base.pal.jpg" "1/2"
                fi
            else
                jpg_resize "$2" "$2" "1/1"
            fi
            ;;
        poster)
            jpg_resize "$2" "$2" "1/1"
            if [ $oversight = 1 ] ; then
                jpg_resize "$2" "$base.thumb.jpg" "1/2"
            fi
            ;;
        banner)
            if [ $oversight = 1 ] ; then
                jpg_resize "$2" "$2" "1/1"
            fi
            ;;
        portrait)
            if [ $oversight = 1 ] ; then
                if [ `sizekb "$2"` -gt 60 ] ; then
                    jpg_resize "$2" "$2" "1/1"
                fi
            fi
            ;;
        *)
            echo "$0: unknown image class [$1]"
            ;;
    esac
    rm -f "$2.pnm" "$base.hd.jpg.pnm" "$base.sd.jpg.pnm" "$base.pal.jpg.pnm" "$base.thumb.jpg.pnm"
}

Q="$OVS_TMP/resize.queue"

add_queue() {
    q="'\\''";
    if [ -n "$1" ] ; then
        args=
        type="$2"
        for i in "$@" ; do
            # Yes sixteen backslashes to get a single one in output
            # 1 = oput
            # *2 to survive final eval - line 250
            # *2 to survive final echo
            # *2 to survive backticks
            # * 2 for sed.
            args="$args '${i//\'/$q}'"
        done
        mkdir -p "$Q.$type"
        perms "$Q.$type"
        echo "fetch_resize $args" >> "$Q.$type/$prefix$$"
        chmod 666 "$Q.$type/$prefix$$"
        perms "$Q.$type/$prefix$$"
        INFO "Queued $2 $3"
    fi
}


# Manage a pid / lock file
running() {
    if [ -f "$1" ] ; then
        if read pid < "$1" ; then
            if [ -n "$pid" ] ; then
                if [ -d /proc/$pid ] ; then
                    return 0
                else
                    rm -f "$1"
                fi
            fi
        fi
    fi
    return 1
}

INFO() {
    echo "[INFO] `date +%H:%M:%S` IMAGES-$thread : $@"
}

ERROR() {
    echo "[ERROR] `date +%H:%M:%S` IMAGES-$thread : $@"
}

process_queue() {

    pq_folder="$1"
    pq_loop=$2
    pq_count=0 
    pq_args="`thread_prefix`.cmd"

    #INFO "Begin Processing folder [$1]"

    if [ -d "$pq_folder" ] ; then
        cd "$pq_folder"
        for f in $prefix* ; do

            if  [ -f "$f" ] && mv "$f" "$pq_args" ; then

                INFO "got image queue file $f"

                cat "$pq_args"
                source "$pq_args"
                rm -f "$pq_args"

                pq_count=$(( $pq_count + 1 ))
            fi
            if [ $pq_loop -eq 0 ] ; then break ; fi
        done
    fi
    #INFO "End processing $1 : $pq_count files"
    # If no files then return error code.
    [ $pq_count -gt 0 ]

}


#caculate in real time to track $$
thread_group() {
    echo "$OVS_TMP/.thread"
}

thread_prefix() {
    echo "`thread_group`.$thread"
}

# A thread will process as many posters as it can, then look for one fanart 
# if anything was found it repeats the cycle otherwise it exists.
start_thread() {
    eval pid=\$\$
    thread=$pid.$1
    #INFO "Thread $pid starting ($$)"
    echo $pid > `thread_prefix`.pid
    while \
        process_queue "$Q.poster" 1 || \
        process_queue "$Q.fanart" 0 || \
        process_queue "$Q.banner" 0 || \
        process_queue "$Q.portrait" 0 ; do
        true
    done
    #INFO "Thread $pid stopping ($$)"
    rm -f `thread_prefix`.pid
}

wc_l() {
    awk 'END { print NR; }'
}

numthreads() {
    nt=0
    for f in "`thread_group`"*.pid ; do
        if running "$f" ; then
            nt=$(( $nt + 1 ))
        fi
    done
    echo $nt
}

tidy() {
    INFO "Thread abort"
    rm -f "`thread_prefix`"*

}


# Synchronise threads
synchronise() {
    sync_file="`thread_group`.sync"
    case "$1" in
        1)
            while running "$sync_file" ; do
                sleep 1
            done
            echo "$pid" > "$sync_file"
            ;;
        0)  rm -f "$sync_file"
            ;;
    esac
}

    
startup() {


    synchronise 1
    tc=`numthreads`
    #INFO "thread count = $tc"
    while [ $tc -lt $maxthreads ] ; do
        ( $0 SPAWN $tc.`date +%H%M%S` & )
        tc=$(( $tc + 1 ))
        sleep 2
    done
    synchronise 0
}

if [ -z "$1" ] ; then
    cat <<HERE
	usage:

        Queue an item
            $0 [portrait|poster|fanart|banner] url file wget options

        Queue an item and start processing queues
            $0 START [portrait|poster|fanart|banner] url file wget options
        
        Start processing queues
            $0 START

        Stop processing queues
            $0 STOP
HERE
	exit 1
fi


if [ "$catalog_make_pal_fanart" = yes -a "$FAMILY" = nmt ] ; then
    get_pal=1
else
    get_pal=0
fi
if [ "$catalog_make_ntsc_fanart" = yes -a "$FAMILY" = nmt ] ; then
    get_ntsc=1
else
    get_ntsc=0
fi

trap tidy 1 2 3 6

case "$1" in

    STOP)
        kill `cat $OVS_TMP/.thread.*`
        ;;

    START)
        shift
        add_queue  "$@"
        startup
        ;;

    SPAWN)
        start_thread "$2"
        ;;

    NOW)
        shift
        fetch_resize "$@"
        ;;
    *)
        add_queue  "$@"
        ;;
esac
