#!/bin/bash

XI_ROOT=$(pwd)
PKGS_OUTPUT=$XI_ROOT/xipkgs
PRIV_KEY=$XI_ROOT/keychain/xi.pem

ERROR="\033[0;31m"
INFO="\033[0;34m"
PASS="\033[0;32m"
NEUTRAL="\033[0;33m"
RESET="\033[0m"

MAKEFLAGS="-j11"
alias make="make $MAKEFLAGS"

extract () {
    FILE=$1
    echo extracting $FILE
    case "${FILE#*.}" in 
        "tar.gz" )
            tar -zxf $FILE
            ;;
        "tar.lz" )
            tar --lzip -xf "$FILE"
            ;;
        "zip" )
            unzip $FILE
            ;;
        * )
            tar -xf $FILE
            ;;
    esac
}

pkgname () {
    echo $(basename $1 .xibuild)
}

xibuild () {
    BUILD_FILE=${@: -1}

    cd $XI_ROOT

    [[ $# = 0 ]] && usage && return 1
    [ ! -f "$BUILD_FILE" ] && echo "$BUILD_FILE not found" && return 1

    clean () {
        # clean up
        rm -rf $PKG_BUILD_DIR
        rmdir $XI_ROOT/tmp > /dev/null 2>&1
    }

    build () {
        printf "\tpassing missing build stage..."
    }
    package () {
        echo "Passing missing package stage"
    }

    BRANCH=HEAD

    source $BUILD_FILE

    PKG_NAME=$(pkgname $BUILD_FILE)

    LOGFILE=$XI_ROOT/logs/$PKG_NAME.log
    PKG_FILE=$PKGS_OUTPUT/$PKG_NAME.xipkg

    PKG_BUILD_DIR=$XI_ROOT/tmp/$PKG_NAME
    PKG_DEST=$XI_ROOT/tmp/$PKG_NAME.package

    # make sure build dir is clean before starting
    rm -rf $PKG_BUILD_DIR

    # make the directories
    mkdir -p $PKG_BUILD_DIR
    mkdir -p $PKG_DEST
    mkdir -p $PKGS_OUTPUT
    mkdir -p $XI_ROOT/logs

    date > $LOGFILE
    echo "Build log for $PKG_NAME from $BUILD_FILE\n" >> $LOGFILE
    printf "\033[0;36m====> $PKG_NAME.xipkg$RESET\n" | tee -a $LOGFILE

    cd $PKG_BUILD_DIR

    # fetch, build then package the package
    ############

    # try get the commit hash for the package
    if git ls-remote -q $SOURCE &> /dev/null; then
        VER_HASH=$(git ls-remote $SOURCE $BRANCH )
    elif hg identify $SOURCE &> /dev/null; then
        VER_HASH=$(hg identify $SOURCE)
    else
        VER_HASH=$(curl -Ls $SOURCE | md5sum)
    fi
    
    VER_HASH=$(echo $VER_HASH | awk '{ print $1 }')

    # If we already have this package, don't waste our time
    if [ -f "$PKG_FILE.info" ] && [ -f "$PKG_FILE" ]; then
        EXISTING_HASH=$(grep -a "VER_HASH" $PKG_FILE.info | sed "s/VER_HASH=//")

        echo "Comparing $EXISTING_HASH to $VER_HASH" >> $LOGFILE

        printf "$INFO\tvalidating commit hash...";
        if echo "$EXISTING_HASH" | grep -q "$VER_HASH"; then
            printf "$NEUTRAL package exists$RESET\n"
            echo "exists $PKG_NAME $DESC" >> $REPORT_LOG
            return;
        else 
            printf "$NEUTRAL package outdated\n"
        fi
    fi

    printf "$INFO\tfetching package...";
    if git ls-remote -q $SOURCE $BRANCH &> /dev/null; then
        git clone $SOURCE . >> $LOGFILE 2>&1 && printf "$PASS fetched $(du -sh $PKG_BUILD_DIR | awk '{ print $1 }') source\n" || return 1;
        git checkout $BRANCH >> $LOGFILE 2>&1 

    elif hg identify $SOURCE &> /dev/null; then
        hg clone $SOURCE . >> $LOGFILE 2>&1 && printf "$PASS fetched $(du -sh $PKG_BUILD_DIR | awk '{ print $1 }') source\n" || return 1;
    else
        DOWNLOADED=$(basename $SOURCE)
        curl -Ls $SOURCE > $DOWNLOADED
        extract $DOWNLOADED >> $LOGFILE 2>&1 && printf "$PASS fetched $(du -sh $PKG_BUILD_DIR | awk '{ print $1 }') source\n" || return 1;
        cd $(ls -d */)
    fi

    printf "$INFO\tbuilding package...";
    build >> $LOGFILE 2>&1 && printf "$PASS built\n" || return 1;
    


    printf "\033[0;34m\tpackaging package...\033[0m";
    package >> $LOGFILE 2>&1 && printf "$PASS packaged\n" ||  return 1;
    
    # add postinstall script
    if command -v postinstall; then
        POSTINSTALL=$( && type postinstall | sed '1,3d;$d')
        if [ ${#POSTINSTALL} != 0 ]; then
            POST_DIR=$PKG_DEST/tmp/xi/postinstall
            mkdir -p $POST_DIR
            echo "#!/bin/sh" > $POST_DIR/$PKG_NAME.sh
            echo $POSTINSTALL >> $POST_DIR/$PKG_NAME.sh
        fi
    fi

    # go back to root, make things easier
    cd $XI_ROOT

    if [ -z "$(ls -A $PKG_DEST)" ]; then
        printf "$FAIL!!!Package is empty!!!$RESET\n"
        return 1;
    fi

    printf "$INFO\tarchiving package...";
    tar -C $PKG_DEST -czf $PKG_FILE ./ >> $LOGFILE 2>&1 && printf "$PASS archived to $(du -sh $PKG_FILE | awk '{ print $1 }')\n" || return 1;


    # create info file
    printf "$INFO\tcreating xipkg.info...";
    PKG_INFO=$PKGS_OUTPUT/$PKG_NAME.xipkg.info

    echo "" > $PKG_INFO
    echo "NAME=$PKG_NAME" >> $PKG_INFO
    echo "DESCRIPTION=$DESC" >> $PKG_INFO
    echo "PKG_FILE=$PKG_NAME.xipkg" >> $PKG_INFO
    echo "CHECKSUM=$(md5sum $PKG_FILE | awk '{ print $1 }')" >> $PKG_INFO
    echo "VER_HASH=$VER_HASH" >> $PKG_INFO
    echo "SOURCE=$SOURCE" >> $PKG_INFO
    echo "DATE=$(date)" >> $PKG_INFO
    echo "DEPS=(${DEPS[*]})" >> $PKG_INFO

    printf "$INFOsigning...";
    # sign the package

    if [ -f "$PRIV_KEY" ]; then
        echo "SIGNATURE=" >> $PKG_INFO
        openssl dgst -sign $PRIV_KEY $PKG_FILE >> $PKG_INFO
    else
        echo "SIGNATURE=">> $PKG_INFO
        echo "unsigned">> $PKG_INFO
        >&2 printf "$ERROR WARNING! No private key: unsigned packages!\n"
    fi
    printf "$PASS signed\n";

    printf "$PASS successfully built $PKG_NAME to $(basename $PKG_FILE)$RESET\n"

    clean
    echo "new $PKG_NAME $DESC" >> $REPORT_LOG
    return 0
}

usage () {
 cat << EOF
usage: $0 [-h] [-o output-dir] [-r working_root]  [-k private_key.pem] build_file.xibuild
    -h          display this help message
    -o          set the output dir for the xipkg files (default: $PWD/xipkgs)
    -r          set the working root for all log and tmp files (default: $PWD)
    -k          set the private key used to sign packages (default: $PWD/keychain/xi.pem)
EOF
}

build-all () {
    FILES=$@

    while test $# -gt 0; do
        case "$1" in
            "-o" )
                shift
                PKGS_OUTPUT=$PWD/$1
                ;;
            "-r" )
                shift
                XI_ROOT=$PWD/$1
                ;;
            "-k" )
                shift
                PRIV_KEY=$PWD/$1
                ;;
            "-h" )
                usage
                ;;
            * )
                REPORT_LOG=$XI_ROOT/xibuild.report.log
                BUILD_FILE=$1
                if xibuild $BUILD_FILE; then 
                    printf "$RESET"
                else
                    printf "$ERROR error! See log$RESET\n"
                    echo "fail $PKG_NAME $DESC" >> $REPORT_LOG
                fi
                cd $XI_ROOT
                ;;
        esac

        shift
    done
}
if [ $# -gt 0 ]; then
    build-all $@ | tee -a xibuild.log
else
    usage; return 1
fi