#!/bin/bash

# Settings
PATCHES_DIR="${PWD}/trunk/patches"
ICONSETS_DIR="${PWD}/trunk/iconsets"
GIT_DIR="${PWD}/git"
DEST_DIR="${PWD}/psi.orig"
WORK_DIR="${PWD}/psi"
PATCH_LOG="${PWD}/long.log"
SHORT_LOG="${PWD}/short.log"
SKIP_BAD_PATCHES="${SKIP_BAD_PATCHES:-0}"
BACKUP_POSTFIX=`date "+%F_%H%M%S"`

# Init
term_width=`tput cols`

die() { echo " !!!ERROR: ${1}"; exit 1; }

prepare_dir() {
  [ -z "${1}" ] && die "dir must not be empty";
  if [ ! -e "${1}" ]; then
    mkdir "${1}"
  else
    echo -en "${1} dir already exists. [b]ackup, [\033[4mr\033[0m]emove, [o]verwrite: "
    read -n 1 act
    case $act in
      b) echo "backuping..."; mv "${1}" "${1}.${BACKUP_POSTFIX}"; mkdir "${1}"  ;;
      o) echo "leave for overwriting" ;;
      ""|r) echo "removing..."; rm -rf "${1}"; mkdir "${1}" ;;
      *) die "unsupported option" ;;
    esac
    
  fi
  [ ! -d "${1}" ] && die "can't prepare dir ${1}"
}

unpack_git() {
  ( cd "${GIT_DIR}"; git archive --format=tar master ) \
  	| ( cd "${1}" ; tar xf - )
  (
    export ddir="${1}"
    cd "${GIT_DIR}"
    git submodule foreach '( git archive --format=tar HEAD ) \
    	| ( cd "${ddir}/${path}" ; tar xf - )'
  )
}

spatch() {
  local PATCH_TARGET="${1}"
  local DIR_OPT=""
  [ -n "${2}" ] && { DIR_OPT="-d ${2}"; }

  echo -n " * applying ${PATCH_TARGET} ..." | tee -a $SHORT_LOG

  local retCode=0
  if ! (patch -p1 --dry-run $DIR_OPT -F 0 -i ${PATCH_TARGET}) >> $PATCH_LOG 2>&1
  then
    if (patch -p1 --dry-run $DIR_OPT -F 2 -i ${PATCH_TARGET}) >> $PATCH_LOG 2>&1
    then
      retCode=1
    else
      retCode=2
    fi
  fi

  if [ $retCode -lt 2 ]
  then
    if (patch -p1 $DIR_OPT -i ${PATCH_TARGET} >> $PATCH_LOG 2>&1)
    then
    	echo "done" | tee -a $SHORT_LOG
    else
    	echo "dry-run ok, but actual failed" | tee -a $SHORT_LOG
        retCode=2
    fi
  else
    echo "failed" | tee -a $SHORT_LOG
  fi

  [ $retCode = 2 ] && [ "${SKIP_BAD_PATCHES}" = "1" ] && { echo "skip buggy patch"  | tee -a $SHORT_LOG; retCode=0; }
  return $retCode
}

[ -f "${PATCH_LOG}" ] && rm "${PATCH_LOG}"
[ -f "${SHORT_LOG}" ] && rm "${SHORT_LOG}"


PATCHES=`(cd "${PATCHES_DIR}"; ls -1 *diff) 2>/dev/null`
[ -z "${PATCHES}" ] && die "patches not found in ${PATCHES_DIR}"
[ -d "${GIT_DIR}/.git" ] || die "${GIT_DIR} is not git repo"



ZENITY_LIST=`echo "${PATCHES}" | sed 's/.*/FALSE \0/'`
UP_TO=`zenity --title 'Patch selector' --text 'Apply patches up to?' \
	--list --radiolist --column '' --column Patch --height 440 \
	--width 600 ${ZENITY_LIST}`
[ "$?" != 0 ] && die "aborted"

prepare_dir "${DEST_DIR}"
prepare_dir "${WORK_DIR}"

echo "patches will be applied up to ${UP_TO}"

unpack_git "${DEST_DIR}"
unpack_git "${WORK_DIR}"
svn export "${ICONSETS_DIR}/system/default" "${WORK_DIR}/iconsets/system/default" --force
svn export "${ICONSETS_DIR}/roster/default" "${WORK_DIR}/iconsets/roster/default" --force
touch "${SHORT_LOG}"

if [ ! -z "${UP_TO}" ]
then
  for p in $PATCHES; do
     fp=$(readlink -f "${PATCHES_DIR}/${p}")
     spatch "${fp}" "${WORK_DIR}"
     rc=$?
     [ "$rc" = 2 ] && die "can't continue"
     [ "$rc" = 1 ] && {
       echo "auto-fixing fuzz"
       ./mkpatch > tmp || die "failed to fix patch"
       mv tmp "$fp"
     }
     [ "${p}" = "${UP_TO}" ] && [ "$1" = "-e" ] && break
     spatch "${fp}" "${DEST_DIR}"
     [ "$?" = 0 ] || die "can't continue"
    [ "${p}" = "${UP_TO}" ] && break;
  done
fi


( cd "${DEST_DIR}"; qconf; )
( cd "${WORK_DIR}"; qconf; )

conf="--disable-growl --disable-bundled-qca --debug --prefix=/usr --no-separate-debug-info --qtdir=/usr"
[ -n "`( cd "${WORK_DIR}"; ./configure --help | grep enable-plugins)`" ] && conf="${conf} --enable-plugins"

( cd "${WORK_DIR}"; ./configure $conf )

for proj in psi.pro.user*; do cp "$proj" "${WORK_DIR}"; done

