#!/bin/sh

# {{{ Copyright
# Copyright 2014 David Woodfall <dave@studioware.org>
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# }}}
#{{{ Init
init()
{
    trap "cleanup" HUP INT ABRT QUIT SEGV TERM KILL PIPE STOP TSTP
    VERSION=0.1
    TMPROOT=$(mktemp -d /tmp/studioware-XXXXXX)
    DIALOGLIST=$TMPROOT/dialog-list
    echo -n "" > $DIALOGLIST
    COREAPPS=$TMPROOT/core-apps
    echo -n "" > $COREAPPS
    FLUXLOCAL=$HOME/.fluxbox/studioware-audio-core
    TMP=$TMPROOT/dialog-out

    LOCALAPPSDIR=$HOME/.local/share/applications
    GLOBALAPPSDIR=/usr/share/applications
    mkdir -p $LOCALAPPSDIR
    WINWIDTH=60
    WINHEIGHT=30
    LISTHEIGHT=30
    TITLE="Choose Core Applications"
    MAINDL="--checklist \"$TITLE\""
    EDL="--msgbox"
    EDLTITLE="Operation finished.\n\n
You may need to log out and log in again to see the changes in XFCE or KDE."
    DL="dialog"
    KAP="kaptain"
    MAINDL="--separate-output --help-button --help-label Default --help-status $MAINDL"
    let WINHEIGHT=$(stty size | awk '{print $1}')
    let LISTHEIGHT=$(stty size | awk '{print $1}')
    let WINWIDTH=$(stty size | awk '{print $2}')
    MAINDL="$MAINDL $WINHEIGHT $WINWIDTH $LISTHEIGHT"
}
# }}}
#{{{ Test if string $1 contains $2
contains()
{
    for opt in $1
    do  
        [[ "$opt" = "$2" ]] && return 0
    done

    return 1
}
#}}}
# {{{ Flags
get_flags()
{
    FLAGS=$*
    contains "$FLAGS" -g && GUI=yes
    contains "$FLAGS" --gui && GUI=yes
    contains "$FLAGS" -d && DEFAULT=yes
    contains "$FLAGS" --default && DEFAULT=yes
    
    [[ -n "$DEFAULT" ]] && set_default
    check_desktops
    [[ -n "$GUI" ]] && do_kdialog || do_dialog
    cleanup
}
# }}}
# {{{ Reset to defaults
set_default()
{
    unset_core

    grep -l X-Studioware-Audio-Core $GLOBALAPPSDIR/*.desktop | \
        while read GLOBAL
    do
        LOCAL=$LOCALAPPSDIR/$(basename $GLOBAL)
        [[ -r $LOCAL ]] && cat $GLOBAL > $LOCAL
        EXEC=$(grep ^Exec= $GLOBAL | cut -d= -f2)
        NAME=$(grep ^Name= $GLOBAL | cut -d= -f2)
        echo "[exec] ($NAME) {$EXEC}" >> $FLUXLOCAL
    done 
    
    pgrep xfdesktop >/dev/null && xfdesktop --reload >/dev/null 2>&1
    
    [[ -n "$GUI" ]] && end_kdialog || end_dialog
    cleanup
}
# }}}
# {{{ Check desktops
# Tried to make this part as fast as possible... excuse the spagetti
check_desktops()
{
    if [ -z "$GUI" ]; then
        clear
        echo "Scanning applications directories. Please wait..."
        setterm -cursor off

        (
            while true
            do
                echo -n "==>"
                sleep 1
                echo -ne "\b"
            done
        ) &

        SPINPID=$!
    else
        echo "start \"Studioware\" -> text;
        text -> @text=\"Scanning application directories.\nPlease wait...\";" | \
        $KAP 2>/dev/null &
        KAPPID=$!
        xsetroot -cursor_name watch
    fi

    if [ -n "$(ls $LOCALAPPSDIR/*.desktop 2>/dev/null)" ]; then
        while read D
        do
            [[ -n "$(grep ^Categories= $D | grep Audio-Core)" ]] && ONOFF=on || ONOFF=off
            LOCALAPPS=$LOCALAPPS"$(basename $D),$(grep ^Name= $D | cut -d= -f2),$(grep ^Exec= $D | cut -d= -f2),$ONOFF
    "
        done <<< "$(grep -l X-Studioware-Audio $LOCALAPPSDIR/*.desktop)"
    fi

    while read D
    do
        if [ "$(basename $D)" = "studioware-core-apps-chooser.desktop" ]; then
            continue
        fi
        [[ -n "$(grep ^Categories= $D | grep Audio-Core)" ]] && ONOFF=on || ONOFF=off
        GLOBALAPPS=$GLOBALAPPS"$(basename $D),$(grep ^Name= $D | cut -d= -f2),$(grep ^Exec= $D | cut -d= -f2),$ONOFF
"
    done <<< "$(grep -l X-Studioware-Audio $GLOBALAPPSDIR/*.desktop)"

    GLOBALAPPS=$(echo "$GLOBALAPPS" | sed '/^$/d')

    while read LINE
    do
        HAVELOCAL=$(echo "$LOCALAPPS" | grep $(echo $LINE | cut -d, -f1))
        [[ -n "$HAVELOCAL" ]] && MERGED="$MERGED$HAVELOCAL
" || MERGED="$MERGED$LINE
"
    done <<< "$GLOBALAPPS"

    MERGED=$(echo "$MERGED" | sed '/^$/d')

    while read LINE
    do
        NAME=$(echo $LINE | cut -d, -f2)
        echo -n \"$NAME\" \"*\" \
            $(echo $LINE | cut -d, -f4)" " >> $DIALOGLIST
    done <<< "$MERGED"

    [[ -z "$GUI" ]] && kill $SPINPID || kill $KAPPID
    xsetroot -cursor_name left_ptr
}
# }}}
# {{{ Do dialog
do_dialog()
{
    sh -c "$DL $MAINDL $(cat $DIALOGLIST)" 2>$COREAPPS
    CHOICE=$?

    if [ $CHOICE != 0 ]; then
        if [ $CHOICE -eq 2 ] && $(sed -i 's%^HELP %%g' $COREAPPS); then
            set_default
        fi
        cleanup $CHOICE
    fi

    set_core
    end_dialog
}
# }}}
# {{{ Do kaptain dialog
do_kdialog()
{
    let CNT=0

    while read LINE
    do
        APPARRAY[$CNT]=$(echo $LINE | cut -d, -f2)

        if [ "$(echo $LINE | cut -d, -f4)" = "off" ]; then
            ONARRAY[$CNT]="!"
        else
            ONARRAY[$CNT]=""
        fi

        let CNT=$CNT+1
    done <<< "$MERGED"

    let CNT=$CNT-1

    LIST="vars :framed -> list;"
    VAR="list :double \"Set Core Applications\" -> "

    for i in `seq 0 $CNT`
    do
        VAR=$VAR"app$i "
    done

    VAR=$VAR";"
    STARTSTR="start \"Studioware\" -> \"echo \" vars "
    ENDSTR="@action(start)=\"Ok\";"
    STARTSTR=$STARTSTR"buttons ;"

    for i in `seq 0 $CNT`
    do
        LINES=$LINES"app$i \"${APPARRAY[i]}\" -> \",${APPARRAY[i]}\" | ${ONARRAY[i]} @;
"
    done

    DEFS="defaults -> \"echo defaults\";"
    BUTTONS="buttons :horizontal -> @exec(start)=\" OK\" @exec(defaults)=\"Defaults\" 
    @close=\"Cancel\";"

$KAP <<END 2>/dev/null | sed '1 s/,//;s/,/\n/g;' > $COREAPPS
$STARTSTR
$LIST
$VAR
$LINES
$DEFS
$BUTTONS
END

    if [ "$(cat $COREAPPS)" = "defaults" ]; then
        set_default
        end_kdialog
    elif [ -z "$(cat $COREAPPS)" ]; then
        cleanup
    else
        set_core
        end_kdialog
    fi
}
# }}}
# {{{ Start kdialog
start_kdialog()
{
$KAP <<END 2>/dev/null
start "Studioware" -> text button;
text -> @text="Scanning directories. Please wait...";
button :horizontal -> @close="OK";
END
    cleanup
}
# }}}
# {{{ End kdialog
end_kdialog()
{
$KAP <<END 2>/dev/null
start "Studioware" -> text button;
text -> @text="Operation finished\n\nYou may need to log out and in again to see the changes in XFCE or KDE.";
button :horizontal -> @close="OK";
END
    cleanup
}
# }}}
# {{{ End dialog
end_dialog()
{
    $DL $EDL "$EDLTITLE" 10 40
    cleanup
}
# }}}
# {{{ Unset core
unset_core()
{
    sed -i 's/X-Studioware-Audio-Core;//' $LOCALAPPSDIR/*.desktop
    echo -n "" > $FLUXLOCAL
}
# }}}
# {{{ Set core apps
set_core()
{
    [[ -z "$(cat $COREAPPS)" ]] && return

    unset_core

    while read LINE
    do
        GLOBAL=$(grep -l ^Name=$LINE$ $GLOBALAPPSDIR/*.desktop)
        LOCAL=$LOCALAPPSDIR/$(basename $GLOBAL)
        cat $GLOBAL > $LOCAL
        EXEC=$(grep ^Exec= $LOCAL | cut -d= -f2)
        NAME=$(grep ^Name= $LOCAL | cut -d= -f2)
        sed -i 's/Categories=/Categories=X-Studioware-Audio-Core;/' $LOCAL
        echo "[exec] ($NAME) {$EXEC}" >> $FLUXLOCAL
    done < $COREAPPS

    pgrep xfdesktop >/dev/null && xfdesktop --reload >/dev/null 2>&1
}
# }}}
# {{{ Cleanup and exit
cleanup()
{
    rm -fr $TMPROOT
    
    if [ -n "$(ps ux | grep core | grep -v grep)" ]; then
        kill $SPINPID 2>/dev/null
    fi
    
    setterm -cursor on
    xsetroot -cursor_name left_ptr
    exit $1
}
# }}}

if [ $UID -eq 0 ]; then
    echo "Do not run this script as root."
    exit 1
fi

init 
get_flags $*

# vim: tw=0
