#!/bin/sh
#
# Copyright (C) 2001, Pehr Johansson (pehr@mcats.net)
#
# Version 0.2.0 (2003-01-06)
#
# SYNOPSIS
# createdisk <outsize> <indir> <outdir> [count]
#

DUKS="du -ks" 
AWK="awk"
export AWK DUKS
# XXX
VERBOSE=1

OUTSIZE=$1
INDIR=$2
OUTDIR=$3
COUNT=$4

function usage()
{
	echo "Usage: createdisk <outsize> <indir> <outdir> [count]"
	echo
	echo "outsize	In megabyte how big each cd can be"
	echo "indir	Path to all diretories to be cdlized"
	echo "outdir	Base path to where cdXXX should be created"
	echo "count	Number of disks to create (cdXXX), default=1"
	echo
}

function compatible()
{
	if ! ${DUKS} &> /dev/null; then
		echo "ERROR: Application '${DUKS}' Failed!";
		exit 1;
	fi
	if ! ${AWK} -W version &> /dev/null; then
		echo "ERROR: Application '${AWK}' Failed!";
		exit 1;
	fi
}

function init()
{
	# Check compatibility
	compatible;

	# Store the max cdsize so we can work with it with cat
	echo `expr ${OUTSIZE} \* 1024` > /tmp/createdisk_maxsize.$$
	cd ${INDIR}; ls -1 | ${AWK} '{system(ENVIRON["DUKS"]" \""$0"\"");}' > /tmp/createdisk_fulllist.$$
	# Create directory listing
	directories=`cat /tmp/createdisk_fulllist.$$ | wc -l | ${AWK} '{printf $1}'`
}

function calculatesize()
{
	skiplines=$1;
	cat /tmp/createdisk_fulllist.$$					\
		| tail -n $((`cat /tmp/createdisk_fulllist.$$		\
		| wc -l`-${skiplines}))					\
		| cat /tmp/createdisk_maxsize.$$ -			\
		| ${AWK} '	BEGIN{					\
					getline;			\
					outsize=$0;			\
					i=0;				\
				}{					\
					if( i + $1  < outsize )		\
						i+=$1;			\
				}END{					\
					printf i			\
				}'

}

function getdirs()
{
	skiplines=$1;
	cat /tmp/createdisk_fulllist.$$ | tail -n $((`cat /tmp/createdisk_fulllist.$$ | wc -l`-${skiplines})) | cat /tmp/createdisk_maxsize.$$ - | ${AWK} 'BEGIN{getline;outsize=$0;i=0; }{ if( i + $1  < outsize ) { i+=$1; print $0 }}' > /tmp/createdisk_onedisk.$$

}

function movedirs()
{
	cdname=$1;
	# Creates a script that moves the files
	printf "cd \"${INDIR}\"" > /tmp/createdisk_movescript.$$
	printf "%s\t%s\n%s" ";" "\\" "mkdir \"${OUTDIR}/$cdname\"" >> /tmp/createdisk_movescript.$$
	echo ${OUTDIR}/$cdname | cat - /tmp/createdisk_onedisk.$$ | ${AWK} 'BEGIN{getline;outdir=$0;}{gsub(".*	", ""); printf ";\t\\\nmv \""$0"\" \""outdir"\"";}' >> /tmp/createdisk_movescript.$$
	# Here we actully move the directories
	sh /tmp/createdisk_movescript.$$
}

function gc()
{
	# Cleanup temporary files
	rm /tmp/createdisk_fulllist.$$ 2> /dev/null
	rm /tmp/createdisk_onedisk.$$ 2> /dev/null
	rm /tmp/createdisk_movescript.$$ 2> /dev/null
	rm /tmp/createdisk_maxsize.$$ 2> /dev/null
}


function findoptimal()
{
	cdname=$1;
	_biggestsize=0;
	_biggestsizeline=0;
	i=0;
	while [ ${i} -le ${directories} ]; do
		size=`calculatesize ${i}`
		if [ ${_biggestsize} -lt ${size} ]; then
			_biggestsize=${size};
			_biggestsizeline=${i};
		fi
		i=$(($i+1));
	done

	# Print out some nice info about the disk that will be created
#	if [ -n "$VERBOSE" ]; then
		echo "Reading directories from : "${INDIR} > /dev/stderr;
		echo "Writing directories to   : "${OUTDIR}"/"$cdname > /dev/stderr;
		echo "Total Disk size          : "`expr $_biggestsize \/ 1024`"M" > /dev/stderr;
		echo "Max Disk size            : "${OUTSIZE}"M" > /dev/stderr;
		echo > /dev/stderr;
#	fi

	printf $_biggestsizeline;
}

if [ -z "$OUTSIZE" -o -z "$INDIR" -o -z "$OUTDIR" ]; then
	usage;
	exit 1;
fi

if [ -z "$COUNT" ]; then
	COUNT=1;
fi

# Check if OUTDIR is actully writeable
if [ ! -d "$OUTDIR" -o ! -w "$OUTDIR" ]; then
	echo "$OUTDIR is not a directory or is not writeable!"
	exit 1;
fi

# Check if INDIR is actully writeable
if [ ! -d "$INDIR" -o ! -w "$INDIR" ]; then
	echo "$INDIR is not a directory or is not writeable!"
	exit 1;
fi

# If count is any other then >1 just set it to 1
if [ $COUNT -lt 1 ]; then
	COUNT=1;
fi

# This is the main loop
_cur_cd=1;
_int_cdnumber=0;
while [ $_cur_cd -le $COUNT ]; do

	# Create cdname
	while [ -d "${OUTDIR}/$_cdname" ]; do
		_int_cdnumber=$(($_int_cdnumber+1));
		if [ $_int_cdnumber -gt 999 ]; then
			echo "Really, isn't 999 cd's enough?!?!" > /dev/stderr
			exit 1;
		fi
		_cdname=cd`echo $_int_cdnumber | ${AWK} '{while (length($0) < 3) $0="0"$0; print $0}'`
	done

	# Initialize some stuff
	init;

	# Check if there really is any directories to move
	dircount=`cat /tmp/createdisk_fulllist.$$ | wc -l`
	if [ $dircount -eq 0 ]; then
		echo "No directories to move!" > /dev/stderr
		gc;
		exit 1;
	fi

	# Find the most optimal combinations of directories
	_biggestindex=`findoptimal $_cdname`;

	# 
	getdirs $_biggestindex;

	# Move the directories to the new location
	movedirs $_cdname;

	# Call the garbage collector to remove all temporary files
	gc;

	_cur_cd=$(($_cur_cd+1));
done
