#!/bin/bash
set -e
APP_SVNID='$HeadURL: http://dione.no-ip.org/svn/ade/tags/1.7.6/bin/adech.sh $ $LastChangedRevision: 6517 $'

. $(ade-config ade_include_prefix)/ade.sh

ADECH_DEFINED_ERRORS=(
    "KEY=ADECH_ERR_MISC; FMT=\"%s\""
)

adech()
{
    local ERRSTACK_REF="$1"; shift
    local RC LABEL 
    local -a NEW_DOLLAR_AT
    local MODE TYPE CHANGELOG_FILE COMMENT

    ###########################################################################
    #
    #  SET ADE OPTIONS
    #
    ###########################################################################

    #  Register application-specific errors
    ade_err_registerdefderrs ADECH_DEFINED_ERRORS
    #  Simple error stacks
    ade_err_resetstack "$ERRSTACK_REF" dumpall=false

    ###########################################################################
    #
    #  PROCESS OPTIONS
    #
    ###########################################################################

    #  Defaults for options
    MODE=unset
    PROGRAM=
    COMMENT="please change this text!"

    #  Register options 
    ade_opt_register "$ERRSTACK_REF" --longoptions=bump-bug,bump-feature,bump-rewrite,check-released,check-unreleased,finalise,program:,comment: --callback-template="adech_opt_handler_%s" || return $?
    ade_msg_register "$ERRSTACK_REF" adech_usage adech_version adech_listpaths || return $?

    #  Process options
    ade_opt_process "$ERRSTACK_REF" NEW_DOLLAR_AT "$@" || return $?
    set -- "${NEW_DOLLAR_AT[@]}" 
    ade_err_debug "$ERRSTACK_REF" 10 "adech: MODE=$MODE"
    [ $MODE != unset ] || ade_msg_usage "$ERRSTACK_REF"

    ##########################################################################
    #
    #  ARGUMENT PROCESSING
    #
    ##########################################################################

    #  Process arguments
    ade_err_debug "$ERRSTACK_REF" 10 "adech: processing args ..."
    [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF"
    CHANGELOG_FILE=$1

    ##########################################################################
    #
    #  FORKING AND LOCKING
    #
    ##########################################################################

    #ade_lck_lock "$ERRSTACK_REF" DUMMY ade_lck_getgenericlockfilename || {
    #    RC=$?
    #    ade_err_error "$ERRSTACK_REF" ADECH_ERR_MISC "locking failed"
    #    return $RC
    #}

    ##########################################################################
    #
    #	GUTS START HERE
    #
    ##########################################################################

    #  Guts
    case $MODE in
        bump)     bump "$ERRSTACK_REF" || return $? ;;
        check)    check "$ERRSTACK_REF" || return $? ;;
        finalise) finalise "$ERRSTACK_REF" || return $? ;;
    esac

    return $ADE_ERR_OK
}

bump()
{
    local ERRSTACK_REF="$1"; shift
    local VERSION CHANGELOG_REWRITE_NUMBER CHANGELOG_FEATURE_NUMBER CHANGELOG_BUG_NUMBER

    ade_err_debug "$ERRSTACK_REF" 10 "bump: CHANGELOG_FILE=$CHANGELOG_FILE, TYPE=$TYPE, pwd=$(pwd)"
    
    if [ ! -f $CHANGELOG_FILE ]; then
        ade_err_debug "$ERRSTACK_REF" 10 "bump: about to call ade_err_error() ..."
        ade_err_error "$ERRSTACK_REF" ADECH_ERR_MISC "please create an empty ChangeLog" 
        return $ADE_ERR_FAIL
    elif [ $(stat -c %s $CHANGELOG_FILE) = 0 ]; then
        VERSION=0
    else
        TYPE=released check "$ERRSTACK_REF" || return $?
        if ! [[ $(head -1 $CHANGELOG_FILE) =~ ^Release\ ([^ .]+)(\.([^ .]+)(\.([^ .]+))?)?\ \(.*\)$ ]]; then 
            ade_err_error "$ERRSTACK_REF" ADECH_ERR_MISC "$CHANGELOG_FILE: malformed first line (it should be 'Release <version-number> (<date-string>)')"
            return $ADE_ERR_FAIL
        fi
        CHANGELOG_REWRITE_NUMBER=${BASH_REMATCH[1]}
        CHANGELOG_FEATURE_NUMBER=${BASH_REMATCH[3]}
        CHANGELOG_BUG_NUMBER=${BASH_REMATCH[5]}
        case $TYPE in
            bug) VERSION=${CHANGELOG_REWRITE_NUMBER:-0}.${CHANGELOG_FEATURE_NUMBER:-0}.$((${CHANGELOG_BUG_NUMBER:-0} + 1)) ;;
            feature) VERSION=${CHANGELOG_REWRITE_NUMBER:-0}.$((${CHANGELOG_FEATURE_NUMBER:-0} + 1)) ;;
            rewrite) VERSION=$((${CHANGELOG_REWRITE_NUMBER:-0} + 1)) ;;
        esac
        if ! [[ $(sed -n 3p $CHANGELOG_FILE) =~ ^\ \ \*\ ([^:]{1,}):\ .*$ ]]; then
            ade_err_error "$ERRSTACK_REF" ADECH_ERR_MISC "$CHANGELOG_FILE: malformed third line (it should be '  * <program-name>: <change-description>')"
            return $ADE_ERR_FAIL
        fi
        PROGRAM=${BASH_REMATCH[1]}
    fi
    [ "X$PROGRAM" != X ] || { ade_err_error "$ERRSTACK_REF" ADECH_ERR_MISC "program unknown (do you need to use '--program=<program>'?)"; return $ADE_ERR_FAIL; }
    { echo "Release $VERSION ($(date)) - UNRELEASED"; echo; echo "  * $PROGRAM: $COMMENT"; echo; cat $CHANGELOG_FILE; } > ChangeLog.$$
    cat ChangeLog.$$ > $CHANGELOG_FILE
    rm -f ChangeLog.$$

    return $ADE_ERR_OK
}

check()
{
    local ERRSTACK_REF="$1"; shift
    local RELEASED_FLAG UNRELEASED_FLAG
   
    { [[ $(head -1 $CHANGELOG_FILE) =~ ^Release\ .*\ \(.*\)$ ]] && RELEASED_FLAG=true; } || RELEASED_FLAG=false
    { [[ $(head -1 $CHANGELOG_FILE) =~ ^Release\ .*\ \(.*\)\ -\ UNRELEASED$ ]] && UNRELEASED_FLAG=true; } || UNRELEASED_FLAG=false

    if [ $TYPE = released ] && $RELEASED_FLAG; then
        :
    elif [ $TYPE = unreleased ] && $UNRELEASED_FLAG; then
        :
    elif [ $TYPE = released ] && $UNRELEASED_FLAG; then
        ade_err_error "$ERRSTACK_REF" ADECH_ERR_MISC "ChangeLog is unreleased!"
        return $ADE_ERR_FAIL
    elif [ $TYPE = unreleased ] && $RELEASED_FLAG; then
        ade_err_error "$ERRSTACK_REF" ADECH_ERR_MISC "ChangeLog is released!"
        return $ADE_ERR_FAIL
    else
        ade_err_error "$ERRSTACK_REF" ADECH_ERR_MISC "ChangeLog is unparsable!"
        return $ADE_ERR_FAIL
    fi

    return $ADE_ERR_OK
}

finalise()
{
    local ERRSTACK_REF="$1"; shift

    TYPE=unreleased check "$ERRSTACK_REF" || return $?
    sed -i "1s/(.*) - UNRELEASED\$/($(date))/" $CHANGELOG_FILE

    return $ADE_ERR_OK
}

adech_opt_handler_bump_bug()
{
    local ERRSTACK_REF="$1"; shift

    MODE=bump
    TYPE=bug

    return $ADE_ERR_OK
}

adech_opt_handler_bump_feature()
{
    local ERRSTACK_REF="$1"; shift

    MODE=bump
    TYPE=feature

    return $ADE_ERR_OK
}

adech_opt_handler_bump_rewrite()
{
    local ERRSTACK_REF="$1"; shift

    MODE=bump
    TYPE=rewrite

    return $ADE_ERR_OK
}

adech_opt_handler_check_released()
{
    local ERRSTACK_REF="$1"; shift

    MODE=check
    TYPE=released

    return $ADE_ERR_OK
}

adech_opt_handler_check_unreleased()
{
    local ERRSTACK_REF="$1"; shift

    MODE=check
    TYPE=unreleased

    return $ADE_ERR_OK
}

adech_opt_handler_finalise()
{
    local ERRSTACK_REF="$1"; shift

    MODE=finalise

    return $ADE_ERR_OK
}

adech_opt_handler_program()
{
    local ERRSTACK_REF="$1"; shift

    PROGRAM="$1"

    return $ADE_ERR_OK
}

adech_opt_handler_comment()
{
    local ERRSTACK_REF="$1"; shift

    COMMENT="$1"

    return $ADE_ERR_OK
}

adech_usage()
{
    local ERRSTACK_REF="$1"; shift
    local USAGETEXT_REF="$1"; shift
    local PASSNO=$1; shift

    ade_err_debug "$ERRSTACK_REF" 10 "adech_usage: sof, USAGETEXT_REF=$USAGETEXT_REF, PASSNO=$PASSNO"

    if [ $PASSNO = 1 ]; then
        eval "$USAGETEXT_REF=\"<ChangeLog-file>\""
    elif [ $PASSNO = 2 ]; then
        eval "$USAGETEXT_REF=\"\
         --program=<program>                 set program name
         --bump-{bug|feature|rewrite}        specify bump type
         --check-{released|unreleased}       check (un)released
         --finalise                          finalise ChangeLog\""
    fi

    return $ADE_ERR_OK
}

adech_listpaths() 
{
    local ERRSTACK_REF="$1"; shift
    local PATHLIST_REF=$1; shift

    eval "$PATHLIST_REF=\"\""

    return $ADE_ERR_OK
} 

adech_version() 
{
    local ERRSTACK_REF="$1"; shift
    local VERSION_REF=$1; shift

    ade_smf_extractversionfromsvnstring "$ERRSTACK_REF" "$APP_SVNID" "$VERSION_REF"

    return $ADE_ERR_OK
} 

ade_gep_main adech "$@"
