#!/bin/ash

# This file is part of PLD batch-installer
# Copyright (C) 2001 CYBER Service
# 
# 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.
#
# Author: Rafał Kleger-Rudomin
# Contributors:
# Packages of choice by Michał Moskal.
# $Id: ui-pkgs,v 1.16 2002/01/02 14:52:39 malekith Exp $


# this is package selector for batch-installer


#set -x


#quote () {
#    echo $@ | sed 's/_/__/g' | sed 's/-/_m/g' | sed 's/+/_p/g'
#}

## read package list from installer.pkgs and mark
## each package with mark_<package_name>

# read all packages from $pkgsfile
# prepare 'hash table'


# output list of groups that has at least one package selected in installer.pkgs
# SIDE EFFECT:
# add a type to pkg_<name>: 1 means standard, 2 means optional
#group_list () {
#local do_output pkg current_group val pkg type
#current_group=""
#do_output=""
#cat $tmp/data-all | while read mark checked group description; do
#    if test "x$mark" = "x*"; then 
#	current_group="$group"
#    else 
#	case "$mark" in
#	!*) 
#	    type=2; pkg=`echo $mark | sed 's/^!//'` ;;
#	[A-Za-z0-9]*) 
#	    type=1; pkg=$mark ;;
#	esac
#	eval "val=\$pkg_`quote $pkg`"
#	if test "$val"; then 
#	    echo "$current_group"
#	    eval "pkg_`quote $pkg`=$type"
#	fi
#    fi
#done | uniq
#}



# produce <item> line for every group
group_items () {
cat $tmp/data-all | while read mark checked group description; do
  if test "x$mark" = "x*"; then 
    group2=`echo $group | sed 's/_/-/g'`
    #if test "x$checked" = "x1"; then description="$description $(nls "(obligatory)")"; fi
    # XXX: if checked=$checked, obligatory sets are always selected...
    # i'm not sure if it's correct
    description=`eval echo $description`
    echo "<item id=$group checked=0>_${group2}_: $description"
  fi
done
}

standard_items () {
local do_output pkg group_item
do_output=""
cat $tmp/data-all | while read mark checked group description; do
    if test "x$mark" = "x*"; then 
	if echo " $pkgs_groups " | grep -q " $group "; then
	    echo "<item ghosted=1 id=xxx>${group_text} `echo $group | sed 's/_/-/g'`                       "
	    do_output=1
	else
	    do_output=""
	fi
    elif test "$do_output"; then
	case "$mark" in
	[0-9A-Za-z]*)
	    pkg="$mark"
	    echo "<item id=$pkg checked=0>`echo $pkg | sed 's/_/-/g'`"
	    ;;
	esac
    fi
done
}

# create items for all optional packages
# based on $pkgs_groups and $grupsfile
optional_items () {
local do_output pkg group_item i gr_id
group_item=""
do_output=""
gr_id=1
cat $tmp/data-all | while read mark checked group description; do
    if test "x$mark" = "x*"; then 
	if echo " $pkgs_groups " | grep -q " $group "; then
	    group_item="<item ghosted=1 id=xxx>${group_text} `echo $group | sed 's/_/-/g'`                       "
	    do_output=1
	else
	    do_output=""
	fi
    elif test "$do_output"; then
	case "$mark" in
	@* )
	    if test "$group_item"; then echo "$group_item"; group_item=""; fi
	    if echo $mark | grep -q '!' ; then
	      i="(optional)"
	    else
	      i=""
	    fi
	    echo "<item ghosted=1>--->>> `echo $mark | sed -e 's/^[!@]*//'` $i:"
	    for i in `echo $checked $group $description | sed -e 's/^[!@]*//'` ; do
	      echo "<item id=$i group=$gr_id checked=0>`echo $i | sed 's/_/-/g'`"
	    done
	    if echo $mark | grep -q '!' ; then
	      echo "<item id='' group=$gr_id checked=0>`nls "NONE"`"
	    else
	      # choice should be always given
	      echo "<item id='' group=$gr_id checked=0>`nls "NONE (_d_o_n_'_t _s_e_l_e_c_t)"`"
	    fi
	    echo "<item ghosted=1 id=''>---<<<"
	    gr_id=$(($gr_id+1))
	    ;;
	!*)
	    if test "$group_item"; then echo "$group_item"; group_item=""; fi
	    pkg=`echo $mark | sed 's/^!//'`
	    echo "<item id=$pkg checked=0>`echo $pkg | sed 's/_/-/g'`"
	    ;;
	esac
    fi
done
}

# select individual packages in the group
# give type as first argument: standard|optional
select_individual () {
local list
eval "list=\$pkgs_${1}_packages"
dial <<EOF
<br>
<meta title="$(nls "Select %s packages" "$2")">
<menu height=18 checked="$list" id=pkgs_$1_packages>
`$1_items`
</menu>

<br>
<button res=4>
EOF
}

# get list1 list2
# show items that are on list2 and not on list1
list_diff () {
    local i j have
    for j in $2; do
	have=""
	for i in $1; do
	    if test "$i" = "$j"; then have=1; break; fi
	done
	test "$have" || echo $j
    done
}

# list standard packages for given groups

list_packages () {
for i in $@; do
    grep "^$i " $tmp/data-packages-with-groups | \
    	sed "s/^$i //" | sed 's/^[!@]*//' | tr ' ' '\n'
done
}

list_standard () {
for i in $@; do
    grep "^$i " $tmp/data-packages-with-groups | \
    	sed "s/^$i //" | grep -v '^[!@]'
done
}

list_optional () {
for i in $@; do
    grep "^$i " $tmp/data-packages-with-groups | \
    	sed "s/^$i //" | grep '^[!@]' | sed 's/^[!@]*//' | tr ' ' '\n'
done
}

list_norm_optional () {
for i in $@; do
    grep "^$i " $tmp/data-packages-with-groups | \
    	sed "s/^$i //" | grep '^!' | sed 's/^!//'
done
}

list_default_of_choice () {
for i in $@; do
    grep "^$i " $tmp/data-packages-with-groups | \
   	sed "s/^$i //" | grep '^@[^!]' | sed 's/^@ *//' | sed 's/ .*//'
done
}

############### main #################


# temporary for testing
PATH=..:.:$PATH . installer-functions

group_text=$(nls "_G_r_o_u_p")

find_config_paths $@
# create initial config if not exists 
test -f $pkgsfile || echo -n >$pkgsfile


# first check if data file is ok
repeated=`grep '^[0-9A-Za-z!]' $groupsfile | sort | uniq -d`
test -z "$repeated" || die "buggy $groupsfile: some packages are duplicated:\n$repeated"

log verb "`nls "Preparing temp files"`"

# find tmp path

tmp=/tmp
if [ -d $HOME/tmp ] ; then
  tmp=$HOME/tmp
fi

# busybox mktemp doesn support -d, sigh!
tmpdir=`mktemp -d $tmp/ui-pkgs-XXXXXX 2> /dev/null` || { 
	tmpdir=ui-pkgs-$$
	mkdir $tmpdir
}
tmp=$tmpdir

# filter out garbage from datafile
grep '^[0-9A-Za-z!@\*]' $groupsfile | \
	sed -e 's/\(!@\|@!\)/@!/' >$tmp/data-all

# list of all packages listed in config
grep '^[0-9A-Za-z]' $pkgsfile | sort | uniq >$tmp/conf-packages

# list of all standard packages listed in data file
grep '^[0-9A-Za-z]' $tmp/data-all | sort | uniq >$tmp/data-standard

# list of all optional packages listed in data file
grep '^!' $tmp/data-all | sed 's/^!//' | sort | uniq >$tmp/data-optional

# list of packages-of-choice(tm)
grep '^@' $tmp/data-all | sed 's/^[^ ]* //' | tr ' ' '\n' \
	| sort | uniq >$tmp/data-of-choice

# find common part
cat $tmp/conf-packages $tmp/data-standard | sort | uniq -d > $tmp/conf-standard
cat $tmp/conf-packages $tmp/data-optional | sort | uniq -d > $tmp/conf-optional
cat $tmp/conf-packages $tmp/data-of-choice | sort | uniq -d > $tmp/conf-of-choice

# find other than standard and optional
cat $tmp/conf-packages $tmp/conf-standard \
    $tmp/conf-optional $tmp/conf-of-choice \
    | sort | uniq -u >$tmp/conf-other

# add artificial group OTHER, and put as a standard all other packages
echo "* 0 `nls "OTHER Packages not listed anywhere"`" >>$tmp/data-all
cat $tmp/conf-other >>$tmp/data-all
cat $tmp/conf-other >>$tmp/data-standard
cat $tmp/conf-other >>$tmp/conf-standard


# list all groups
grep '^\* ' $tmp/data-all | sed 's/\* *[0-9] *//' | sed 's/ .*//' >$tmp/data-groups

current_group="none_group"
cat $tmp/data-all | while read mark checked group description; do
    if test "x$mark" = "x*"; then 
	current_group="$group"
    else 
	#pkg=`echo $mark $checked $group $description | sed 's/^[!@]*//'`
	#echo "$current_group $pkg"
	case $mark in 
	  @* )
	    echo $current_group $mark $checked $group $description | \
	    	sed -e 's/@\(!\?\)[^ ]* */@\1/'
	    ;;
	  * )
	    echo $current_group $mark
	    ;;
	esac
    fi
done >$tmp/data-packages-with-groups

log verb "`nls "Finding selected groups"`"

# if we had -f or -w option to uniq... eh
pkgs_groups=""
echo -n "         "
for i in `cat $tmp/data-groups`; do 
    echo -n '.'
    list_packages $i >$tmp/tmp
    test -z "`cat $tmp/tmp $tmp/conf-packages | sort \
    	| uniq -d`" || pkgs_groups="$i $pkgs_groups" || :
done
echo

#echo "Selected: $pkgs_groups"


pkgs_standard_packages=`cat $tmp/conf-standard`
pkgs_optional_packages=`cat $tmp/conf-optional $tmp/conf-of-choice`

add_optional=yes

while : ; do
    [ "$just_dump" != "" ] && break
    if [ "$add_optional" = "yes" ] ; then
      add_optional=1
    fi

    # save value
    pkgs_groups_old="$pkgs_groups"

dial <<EOF
<meta title="$(nls "Package's groups")">
<menu height=15 checked="$pkgs_groups" id=pkgs_groups res=1>
`group_items`
</menu>
<br>
<button res=4 caption="$(nls "_Select _standard packages")"><br>
<button res=5 caption="$(nls "_Select _optional packages")"><br>
<button res=1> <button res=6 caption="$(nls "_Refresh")"> <button res=2 caption="$(nls "_Cancel")"><br><br>
<check checked=$add_optional id=add_optional> `nls "Add optional packages when selecting group"`
EOF

    # find newly added groups and unchecked groups
    echo "$pkgs_groups"     | tr ' ' '\n' >$tmp/tmp1
    echo "$pkgs_groups_old" | tr ' ' '\n' >$tmp/tmp2
    # the common part
    cat $tmp/tmp1 $tmp/tmp2 | sort | uniq -d >$tmp/tmp
    # subtraction
    new_groups=`cat $tmp/tmp1 $tmp/tmp | sort | uniq -u`
    removed_groups=`cat $tmp/tmp2 $tmp/tmp | sort | uniq -u`
    rm -fr $tmp/tmp $tmp/tmp1 $tmp/tmp2

    if test "$removed_groups"; then
	echo "Removing groups:"
	echo "$removed_groups"
	# remove all packages for removed groups
	#removed_groups=`list_diff $pkgs_groups $pkgs_groups_old`
	
	# doing this with uniq was buggy...
	re=""
	for p in `list_standard $removed_groups` ; do
	  re="$re\|$p"
	done
	# re now contains regexp with all lines to be removed
	pkgs_standard_packages=$(echo $pkgs_standard_packages | \
		tr ' ' '\n' | sed "s/^\(shouldnthappen$re\)$//")
		
	re=""
	for p in `list_optional $removed_groups` ; do
	  re="$re\|$p"
	done
	pkgs_optional_packages=$(echo $pkgs_optional_packages | \
		tr ' ' '\n' | sed "s/^\(shouldnthappen$re\)$//")
    fi

    if test "$new_groups"; then
	echo "Adding groups:"
	echo "$new_groups"
	# put standard packages as selected by default
	pkgs_standard_packages="$pkgs_standard_packages `list_standard $new_groups`"
	pkgs_optional_packages="$pkgs_optional_packages `list_default_of_choice $new_groups`"
	if [ "$add_optional" = yes ] ; then
	  pkgs_optional_packages="$pkgs_optional_packages `list_norm_optional $new_groups`"
	fi
    fi

    # res is used by all dialogs, change to result
    result=$res
    case "$result" in
    1) break ;;
    2) exit 1 ;;
    3) lists ;;
    4) select_individual standard "`nls standard`" ;;
    5) select_individual optional "`nls optional`" ;;
    6) : ;;
    esac

done

log verb "`nls "Saving package set to %s" "$pkgsfile"`"
echo -n >$pkgsfile
for i in $pkgs_standard_packages $pkgs_optional_packages; do
    echo "$i" >>$pkgsfile
done

# vim:ft=sh
