#!/bin/bash -
PROG=${0##*/}
LPBUG=
PROJECT=
SERIES=
PKGNAME=
PKGVER=1.0
DESTDIR=$(pwd)
DISTRIB=$(lsb_release -cs)
REBOOT=false

color_text()
{
    local _cid
    case "$1" in
        ('blue') _cid=34 ;;
        ('red') _cid=31 ;;
        ('purple') _cid=35 ;;
        ('cyan') _cid=36 ;;
        ('yellow') _cid=33 ;;
        ('green') _cid=32;;
        ('white') _cid=37 ;;
    esac
    echo "\x1b[$_cid;1m${@:2}\x1b[0m"
}

color_print()
{
    echo -e $(color_text $@)
}

die()
{
    echo -e "\x1b[31;1mError: $1\x1b[0m" >&2
    exit 1
}

_create_pkg_skel()
{
    local _pkgname=${PKGNAME}_${PKGVER}${PROJECT}1

    [[ -n "$SERIES" ]] &&
        _pkgname=${_pkgname}${SERIES}1

    [[ -d $DESTDIR/$_pkgname ]] && \
        die "$DESTDIR/$_pkgname exists."

    mkdir -p $DESTDIR/$_pkgname
    cd $DESTDIR/$_pkgname
    ! $(dh_make -s -n -e ${DEBEMAIL} -p $_pkgname -y > /dev/null 2>&1) && \
        die "dh_make fail($?)."

    sed -e '/'$PKGNAME'/s/unstable/'$DISTRIB'/' \
        -e '/urgency/s/=.*/=high/' \
        -i $DESTDIR/$_pkgname/debian/changelog

    sed '/dh.*@/s/$/--with modaliases/g' \
        -i $DESTDIR/$_pkgname/debian/rules

    if $REBOOT; then
        cat > /tmp/reboot-code-piece.tmp << EOF
        # Trigger reboot after package is installed
        if [ -x /usr/share/update-notifier/notify-reboot-required ]; then
            /usr/share/update-notifier/notify-reboot-required
        else
            echo "*** System restart required ***" > /var/run/reboot-required
            echo "\$DPKG_MAINTSCRIPT_PACKAGE" >> /var/run/reboot-required.pkgs
        fi
EOF

        sed -e '/ configure/r /tmp/reboot-code-piece.tmp' \
               $DESTDIR/$_pkgname/debian/postinst.ex > $DESTDIR/$_pkgname/debian/postinst
        chmod +x $DESTDIR/$_pkgname/debian/postinst
        rm -f /tmp/reboot-code-piece.tmp
    fi

    echo $DESTDIR/$_pkgname
    return 0
}

_check_debian_dir()
{
    [[ -n "$1" ]] && [[ -d "$1/debian" ]] &&
        return 0
    die "Cannot find directory $_dst/debian"
}

_write_copywrite()
{
    local _dst=$1
    local _year=$(date +%Y)

    _check_debian_dir $_dst

    cat << EOF > $_dst/debian/copyright
This work was packaged for Ubuntu by:

    $DEBFULLNAME <$DEBEMAIL>

Copyright:

    <Copyright (C) $_year Canonical Ltd. >

License:

    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 3 of the License, or
    (at your option) any later version.

    This package 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, see <http://www.gnu.org/licenses/>.

On Ubuntu systems, the complete text of the GNU General
Public License version 3 can be found in '/usr/share/common-licenses/GPL-3'.

The Ubuntu packaging is:

    Copyright (C) $_year Canonical Ltd.

and is licensed under the GPL version 3, see above.
EOF
}

_write_control()
{
    local _dst=$1
    local _depend _shortdesc _desc

    _check_debian_dir $_dst

    shift # skip first param
    while [[ "$1" ]]; do
        case "$1" in
            --depend)
                _depend=$2
                shift ;;
            --short-desc)
                _shortdesc=$2
                shift ;;
            --desc)
                _description=$2
                shift ;;
        esac
        shift
    done

    BUGS=
    for b in $LPBUG
    do
        BUGS="$BUGS LP:#$b"
    done
    BUGS=$(echo $BUGS | sed -e 's/[[:space:]]/,/')

    [[ -z "$_shortdesc" ]] && \
        _shortdesc="OEM packages for $PROJECT that fixes issues"

    [[ -z "$_description" ]] && \
        _description=$(echo The $DEBNAME package includes patches to fix issue $BUGS)

    sed -e '/^#/d' \
        -e '/^Homepage/d' \
        -e 's/Description.*/Description: '"$_shortdesc"'/' \
        -e 's/Section: unknown/Section: devel/' \
        -e '/Standards-Version:/s/: .*/: 3.9.5/' \
        -e '/Description/iXB-Modaliases: ${modaliases}' \
        -e '/Description/,/^$/{n;d}' \
        -i $_dst/debian/control

    [[ -n "$_depend" ]] && \
        sed -e '/^Depends:/s/$/, '"$_depend"'/' -i $_dst/debian/control

    sed -e '/Build-Depends:/s/$/, dh-modaliases/' \
        -i $_dst/debian/control

    echo $_description | fold -w 80 -s | sed 's/^/ /g' >> $_dst/debian/control
}

_write_modalias()
{
    local _dst=$1
    local _alias=$2

    _check_debian_dir $_dst
    cat << EOF > $_dst/debian/modaliases
# Modalias for $PKGNAME
# 
# Example:
#    alias oemalias:* oem_include $PKGNAME
#    alias oemalias:buCNBp80BB oem_include $PKGNAME
EOF
    if [[ -n "$2" ]]; then
        [[ -f "$2" ]] && \
            cat $2 >> $_dst/debian/modaliases || \
            echo $2 >> $_dst/debian/modaliases
    fi
    sed '/^$/d' -i $_dst/debian/modaliases
}

_clean_unnecessary()
{
    local _dst=$1
    cd $_dst
    rm -f debian/*.ex \
          debian/*.EX \
          debian/README* \
          debian/docs \
          debian/copyright
}

create_simple_template()
{
    local _target

    [[ -z "$PKGNAME" ]] && \
        die "Please specify package name"

    _target=$(_create_pkg_skel)
    [[ -z "$_target" ]] && exit 1

    _clean_unnecessary $_target
    _write_control $_target --depend volatile-task-core
    _write_copywrite $_target
    _write_modalias $_target

    echo "Process done, the template will be placed in $_target"
}

create_dkms_meta_template()
{
    create_meta_template dkms $@
}

create_meta_template()
{
    local _target
    local _depend=volatile-task-core
    local _modalias
    local _debfiles
    local _tmp
    local _dkms=false

    [[ -z "$PKGNAME" ]] && \
        die "Please specify package name"

    while [[ "$1" ]]; do
        case "$1" in
            dkms)
                [[ ! "$PKGNAME" =~ .*dkms-meta$ ]] &&
                    die "DKMS Meta package name should be ended with $(color_text 'blue' '-dkms-meta')"
                _dkms=true
            ;;
            -P|--package)
                if check_param $2; then
                    _debfiles=$(echo $_debfile ${2//,/ })
                    shift
                fi ;;
        esac
        shift
    done

    for p in $_debfiles; do
        p=$(readlink -e $p)
        [[ ! -f "$p" ]] && continue
        [[ ! "$p" =~ .*\.deb ]] && continue
        _tmp=$(echo $_tmp $p)
    done

    [[ -z "$_tmp" ]] && \
        die "Please specify dkms package with -P." ||
        _debfiles=$_tmp

    _target=$(_create_pkg_skel)
    [[ -z "$_target" ]] && exit 1

    _tmp=$(mktemp)
    mkdir -p $_target/addon
    touch $_target/addon/${PKGNAME}.remove
    for p in $_debfiles; do
        echo "Adding debian package ${p##*/} to $_target/addon"
        cp $p $_target/addon
        _depend="$_depend, $(dpkg-deb -f $p Depends)"

        ! $_dkms &&continue

        dpkg-deb -f $p Modaliases | while read line
        do
            local _category=$(echo $line | sed 's/\(.*\)(.*)/\1/g')
            echo -e "##\n## modaliases from ${p##*/}\n##" >> $_tmp
            echo $line | sed 's/.*(\(.*\))/\1/g' | \
                         sed 's/,/\n/g' | \
                         sed 's/^[[:space:]]*/alias /g' | \
                         sed 's/[[:space:]]*$/ '"$_category $PKGNAME"'/g' \
                        >> $_tmp
        done
    done

    cat << EOF > $_target/debian/install
addon usr/share/volatile
EOF

    _clean_unnecessary $_target
    _write_control $_target --depend "$_depend"
    _write_copywrite $_target
    _write_modalias $_target $_tmp
    rm -f $_tmp

    echo "Process done, the template will be placed in $_target"
}

create_cmdline_template()
{
    local _target
    local _depend=oem-${PROJECT}-cmdline

    PKGNAME=oem-kernel-cmdline-$(echo $LPBUG | awk '{print $1}')

    _target=$(_create_pkg_skel)
    [[ -z "$_target" ]] && exit 1

    _clean_unnecessary $_target
    _write_control $_target --depend "$_depend" --short-desc "OEM kernel parameter package for ${PROJECT}" \
        --desc "This package will apply kernel parameter for fixing issue $(for l in $LPBUG; do echo "lp: #$l,"; done | sed 's/,$//')"
    _write_copywrite $_target
    _write_modalias $_target

    cat << EOF > $_target/${PKGNAME}.conf
# This config file is used to generate kernel command in grub.cfg
# These variables will be exported:
#   OEM_KERNEL_PARAM       : kernel parameters use after system installed.
#   OEM_EARLY_KERNEL_PARAM : kernel parameters ONLY be used in earlyboot stage.
#   OEM_GRUB_*             : GRUB configurations, please refert to grub.cfg
#   OEM_EARLY_GRUB_*       : GRUB configurations ONLY be used in earlyboot stage.

# useful functions e.g: check_vga, check_pciid ...
. /lib/oem-${PROJECT}-cmdline/common.sh

export OEM_KERNEL_PARAM=
export OEM_EARLY_KERNEL_PARAM=
EOF

    cat << EOF > $_target/debian/install
${PKGNAME}.conf usr/share/oem-${PROJECT}-cmdline/conf.d/
EOF

    echo "Process done, the template will be placed in $_target"
}

check_param()
{
    local param=$1
    [[ -n "$param" && ! "$param" =~ ^\-.* ]] && \
        return 0
    return 1
}

parse_param()
{
    local _opt
    while [[ "$1" ]]; do
        case "$1" in
            -p|--project)
                if check_param $2; then
                    PROJECT=$2
                    shift
                fi ;;
            -d|--dest)
                if check_param $2; then
                    DESTDIR=$2
                    shift
                fi ;;
            -l|--lp)
                if check_param $2; then
                    LPBUG=$(echo $LPBUG ${2//,/ })
                    shift
                fi ;;
            -D|--distrib)
                if chekc_param $2; then
                    DISTRIB=$2
                    shift
                fi ;;
            -v|--version)
                if check_param $2; then
                    PKGVER=$2
                    shift
                fi ;;
            -r|--reboot)
                REBOOT=true ;;
            [a-zA-Z0-9]*)
                [[ ! $1 =~ .*\.deb$ ]] && \
                    PKGNAME=$1 || \
                    _opt="$_opt $1" ;;
            -x|--debug)
                : ;;
            *)
                [[ -n "$1" ]] && \
                    _opt="$_opt $1" ;;
        esac
        shift
    done

    [[ -z "$PROJECT" ]] && \
        die "Please specify project name (e.g: stella-ludao)"

    if [[ "$PROJECT" =~ .*-.* ]]; then
        SERIES=${PROJECT##*-}
        PROJECT=${PROJECT%%-*}
    fi

    [[ -z "$LPBUG" ]] && \
        die "Please specify launchpad bug id"

    [[ -z "$DEBEMAIL" || -z "$DEBFULLNAME" ]] && \
        die "Please export \$DEBFULLNAME and \$DEBEMAIL"

    parse_param_result=$(echo $_opt)
}

usage()
{
    echo "$(color_print 'white' "$PROG helps generate debian package template for OEM projects.")"
    echo 
    echo "USAGE:" 
    echo "  Create simple template"
    echo "      $(color_print 'yellow' "$PROG simple -l|-lp <bug id>,<bug id> -p <project> <package name>")"
    echo
    echo "  Create meta template"
    echo "      $(color_print 'yellow' "$PROG meta -l|-lp <bug id>,<bug id> -p <project> -P <package>,<pacakge> <package name>")"
    echo 
    echo "  Create DKMS meta template"
    echo "      $(color_print 'yellow' "$PROG dkms-meta -l|-lp <bug id>,<bug id> -p <project> -P <dkms package>,<dkms pacakge> <package name>")"
    echo
    echo "    $(color_print 'red' "Note: DKMS meta package name should be ended with $(color_print 'green' '-dkms-meta')")"
    echo 
    echo "  Create kernel command line template"
    echo "      $(color_print 'yellow' "$PROG cmdline -l|-lp <bug id>,<bug id> -p <project>")"
    echo 
    echo "    $(color_print 'red' "Note: Kernel command line package name will be automatically generated")"
    echo
    echo "  Common options:"
    echo "      -l|-lp <bug id>           Launchpad bug id"
    echo "      -p|--project <project>    OEM project name (e.g stella, stella-ludao)"
    echo "      -d|--dest <destination>   Destination folder (default: $DESTDIR)"
    echo "      -v|--version <version>    Specify package version (default: $PKGVER)"
    echo "      -r|--reboot               Notify reboot after package is installed"
    echo
    exit 0
}

echo $@ | grep -E "(\-x|\-\-debug)" && set -x

_command=
_param=${@:2}
case "$1" in
    simple)
        _command=create_simple_template ;;
    meta)
        _command=create_meta_template ;;
    dkms-meta)
        _command=create_dkms_meta_template ;;
    cmdline)
        _command=create_cmdline_template ;;
    help)
        usage ;;
    *)
        die "Invalid command {${1}}.\n$(color_text 'white' 'Valid commands are: simple, dkms-meta, cmdline and help.')" ;;
esac

parse_param $_param
$_command $parse_param_result
