#!/bin/sh

########## ####      ####
########## ####      ####
##      ## ##  ##  ##  ##
##      ## ##  ##  ##  ##
########## ##    ##    ## - PACKAGE MANAGER FOR SIMPLE LINUX
########## ##    ##    ## - AUTHOR -- TOLA MIRONCENKO
##         ##          ##
##         ##          ##
##         ##          ##
##         ##          ##

#---------------- variables --------------------------
version="1.0.0"
export rootdir=/
repofile=$rootdir/etc/pm/repo
packagesqueryfile=$rootdir/usr/share/pm/query
reposquerydir=$rootdir/usr/share/pm/repos
cachedpkgdir=$rootdir/var/cache/pm/pkg
installedpackagesdir=$rootdir/usr/share/pm/packages
#-----------------------------------------------------

#----- colors -------
RESET="\033[0m"
GREEN="\033[0;32m"
RED="\033[0;31m"
BRED="\033[1;31m"
YELLOW="\033[1;33m"
BWHITE="\033[1;37m"
BBLUE="\033[1;34m"
BGREEN="\033[1;32m"
#--------------------

#------------ check status function ------------
check() {
    if [ $1 -ne 0 ]; then
        printf "$BBLUE**$BWHITE $2 [$BRED ERROR $BWHITE]\n$RESET"
        exit $1
    fi
    printf "$BBLUE**$BWHITE $2 [$BGREEN SUCCESS $BWHITE]\n$RESET"
}
#-----------------------------------------------

#---------------- check root priveleges function ------------------------
checkroot() {
    if [[ $(id -u) != 0 ]]; then
        printf "$BBLUE**$BWHITE You must be root [$BRED ERROR $BWHITE]\n$RESET"
        exit 1
    fi
}
#------------------------------------------------------------------------

#----------------- add(install) package function ------------------------
add() {
    shift 1
    if [[ "$1" == "" ]]; then
        help
        exit 0
    fi
    for i in $@; do
        case $i in
            add|a)
                continue
                ;;
        esac
    done
    for i in $@; do
        case $i in
            add|a)
                continue
                ;;
            *)
                down $i
                ;;
        esac
    done
    for i in $@; do
        case $i in
            add|a)
                continue
                ;;
            *)
                unpack $cachedpkgdir/$i.pkg.gz
                ;;
        esac
    done
}
a() {
    add $@
}
#------------------------------------------------------------------------

#-------------------- download package without install function ---------
down() {
    if [[ ! $1 ]]; then
        help
        exit 0
    fi
    servers=$(/usr/bin/cat $repofile)
    check $? "Read repositories"
    for i in $servers; do
        serverdir=$(echo $i | sed -e "/http:\/\//s///")
        serverdir=$(echo $serverdir | sed -e "/ftp:\/\//s///")
        repoquery=$(/usr/bin/cat $reposquerydir/$serverdir/query | sed -e '/.pkg.gz/s///')
        for j in $repoquery; do
            if [[ $j == $1 ]]; then
                if [ ! -f $cachedpkgdir/$1.pkg.gz ]; then
                    printf "$YELLOW**$RESET Downloading $YELLOW$serverdir: $Bwhite$j\n$RESET"
                    echo $i/$1.pkg.gz
                    wget $i/$1.pkg.gz -P $cachedpkgdir
                    check $? "Download package"
                    # if [[ "$?" == "0" ]]; then
                    #     printf "$YELLOW**$GREEN successful downloaded $1\n$RESET"
                    #     return
                    # else 
                    #     printf "$YELLOW**$RED error:$RESET can't download package\n"
                    #     exit 1
                    # fi
                else
                    printf "$YELLOW**$GREEN successful downloaded $1\n$RESET"
                    return
                fi 
                return                
            fi
        done
    done
    printf "$BBLUE**$BWHITE Can't find package $1 [$BRED ERROR $BWHITE]\n$RESET"
    exit 1
}
download() {
    down $1
}
#------------------------------------------------------------------------

#-------------------- unpack local package archive ----------------------
unpack() {
    packagename=$(echo $1 | sed -e "/.gz/s///")
    packagename=${packagename#*pkg/}
    printf "$YELLOW**$GREEN Installing ${packagename%.pkg*}\n$RESET"
    if [ ! -f $packagesqueryfile ]; then
        printf "$BBLUE**$BWHITE Can't find $packagesqueryfile [$BRED ERROR $BWHITE]\n$RESET"
    fi
    installed=false
    for i in $(/usr/bin/cat $packagesqueryfile); do
        if [ "$i" = "${packagename%.pkg*}" ]; then
            export installed=true
            break
        fi
    done
    if [[ "$installed" == "true" ]]; then
        printf "$YELLOW**$RESET Package already installed:$YELLOW reinstalling\n$RESET"
    fi
    tar -xvf $1 -C $rootdir/tmp &> /dev/null
    cd $rootdir/tmp/$packagename
    if [ -f deps ]; then
        printf "$YELLOW**$GREEN Checking deps\n$RESET"
        deps=$(/usr/bin/cat deps)
        for dep in $deps; do 
            have=false
            for pack in $(/usr/bin/cat $packagesqueryfile); do
                if [ $pack = $dep ]; then
                    have=yes
                    break
                fi
            done
            if [ "$have" = "false" ]; then
                pkgnow=$packagename
                add "" $dep
                unpack $cachedpkgdir/$pkgnow.gz
                return
            fi
        done
        mkdir $installedpackagesdir/$packagename &> /dev/null
        mv -v deps $installedpackagesdir/$packagename &> /dev/null
    fi
    mkdir $installedpackagesdir/$packagename &> /dev/null
    mv -v list $installedpackagesdir/$packagename &> /dev/null
    cp -r ./* $rootdir/
    if [ -f $rootdir/post_install ]; then
        rm $rootdir/post_install
    fi
    if [ -f $rootdir/tmp/$packagename/post_install ]; then
        printf "$YELLOW**$GREEN post_install script ${packagename%.pkg*}\n$RESET"
        /usr/bin/sh -c $rootdir/tmp/$packagename/post_install &> /dev/null
    fi
    if [[ "$installed" == "false" ]]; then
        echo ${packagename%.pkg*} >> $packagesqueryfile
    fi
    rm -rv $rootdir/tmp/$packagename &> /dev/null
    printf "$YELLOW**$GREEN Installed ${packagename%.pkg*} successful\n$RESET"
}
u() {
    unpack $1
}
#------------------------------------------------------------------------

#------------------ delete package function -----------------------------
del() {
    printf "$YELLOW**$GREEN deleting\n$RESET"
    shift 1
    for i in $@; do
        printf "$YELLOW**$GREEN deleting $i\n$RESET"
        if [ ! -f $installedpackagesdir/$i.pkg/list ]; then
            printf "$BBLUE**$BWHITE package not installed ($i) [$BRED ERROR $BWHITE]\n$RESET"
            exit 1
        fi
        for file in $(/usr/bin/cat $installedpackagesdir/$i.pkg/list); do
            rm -v $rootdir/$file
        done
        # rm -v $rootdir/$(/usr/bin/cat $installedpackagesdir/$i.pkg/list)
        rm -rv $installedpackagesdir/$i.pkg &> /dev/null
        packs=$(cat $packagesqueryfile)
        rm $packagesqueryfile
        for pack in $packs; do
            if [ "$pack" = "$i" ]; then
                continue
            fi
            echo $pack >> $packagesqueryfile
        done
        # sed -i "s/$i/d" $packagesqueryfile
        printf "$YELLOW**$GREEN delete $i successful\n$RESET"
    done
}
d() {
    del $@
}
#------------------------------------------------------------------------

#------------------- list files in package function ---------------------
list() {
    if [[ "$1" == "" ]]; then
        for i in $(/usr/bin/cat $packagesqueryfile); do
            filelist=$(/usr/bin/cat $installedpackagesdir/$i.pkg/list)
            for j in $filelist; do
                printf "$YELLOW$i: $BWHITE$j$RESET\n"
            done
        done
        exit 0
    fi
    if [[ "$(/usr/bin/cat $packagesqueryfile | grep $1)" == "" ]]; then
        printf "$BBLUE**$BWHITE Package is not installed [$BRED ERROR $BWHITE]\n$RESET"
        exit 1
    fi
    filelist=$(/usr/bin/cat $installedpackagesdir/$1.pkg/list)
    for i in $filelist; do
        printf "$YELLOW$1: $BWHITE$i$RESET\n"
    done
}
l() {
    list $1
}
#------------------------------------------------------------------------

#------------------- show installed packages function -------------------
query() {
    packagesquery=$(/usr/bin/cat $packagesqueryfile)
    if [[ "$packagesquery" == "" ]]; then
        printf "$YELLOW**$BWHITE No installed packages\n$RESET"
        exit 0
    fi
    for i in $packagesquery; do
        printf "$BWHITE$i\n$RESET"
    done
}
q() {
    query
}
#------------------------------------------------------------------------

#--------------------- show help function -------------------------------
help() {
    printf "
        $YELLOW**$GREEN pm usage$RESET :
        $BWHITE add, a [package name] - download and install from repository
         unpack, u [/path/to/package/archive] - unpack(install) from local package archive
         down, download [package name] - download package from repository without install
         del, d [package name] - delete package
         list, l [package name] - list files in package
         search, ss [package name] - search package in repository
         query, q - show installed packages
         help - this help message
         clear - clear all package archives from cached packages directory
         sync, s - synchronize repository
         deps [package name] - show package dependencies

        $YELLOW**$GREEN examples$RESET :
        $BWHITE pm add dnsmasq
         pm unpack ./dnsmasq.pkg.gz
         pm down dnsmasq
         pm search dnsmasq
         pm help
         pm clear
         pm sync
         pm del dnsmasq
         pm list dnsmasq
         pm query
    \n$RESET"
}
#------------------------------------------------------------------------

#------------------- sync repo function ---------------------------------
sync() {
    servers=$(/usr/bin/cat $repofile)
    for i in $servers; do
        printf "$YELLOW**$GREEN Sync $BWHITE$i\n$RESET"
        serverdir=$(echo $i | sed -e "/http:\//s///")
        serverdir=$(echo $serverdir | sed -e "/ftp:\//s///")
        mkdir -p $reposquerydir/$serverdir &> /dev/null
        wget $i/query -O $reposquerydir/$serverdir/query &> /dev/null
        check $? "Sync $i"
    done
}
s() {
    sync
}
#------------------------------------------------------------------------

#----------------- search package in repo function ----------------------
search() {
    servers=$(/usr/bin/cat $repofile)
    if [[ ! $1 ]]; then
        for i in $servers; do
            serverdir=$(echo $i | sed -e "/http:\/\//s///")
            serverdir=$(echo $serverdir | sed -e "/ftp:\/\//s///")
            repoquery=$(/usr/bin/cat $reposquerydir/$serverdir/query | sed -e '/.pkg.gz/s///')
            for j in $repoquery; do
                printf "$YELLOW$serverdir: $BWHITE$j\n$RESET"
            done
        done
        exit 0
    fi
    found=false
    for i in $servers; do
        serverdir=$(echo $i | sed -e "/http:\/\//s///")
        serverdir=$(echo $serverdir | sed -e "/ftp:\/\//s///")
        repoquery=$(/usr/bin/cat $reposquerydir/$serverdir/query | sed -e '/.pkg.gz/s///')
        for j in $repoquery; do
            if [[ $j =~ $1 ]]; then
                printf "$YELLOW$serverdir: $BWHITE$j\n$RESET"
                found=true
            fi
        done
    done
    [ "$found" = "false" ] && printf "$YELLOW**$RED error:$RESET can't find package ($1)\n"
}
ss() {
    search $1
}
#------------------------------------------------------------------------

#------------------- clear cached packages directory --------------------
clear() {
    rm -v $cachedpkgdir/*
}
#------------------------------------------------------------------------

#--- show package dependencies function ---
deps() {
    if [ "$1" = "" ]; then
        help
        exit 1
    fi
    if [ ! -f $installedpackagesdir/$1.pkg/deps ]; then
        printf "$YELLOW**$BWHITE No deps\n$RESET"
        exit 0
    fi
    cat $installedpackagesdir/$1.pkg/deps
}
#------------------------------------------

#--- build package uses PMBUILD file function ---
buildpkg() {
    if [ ! -f ./PMBUILD ]; then
        if [ "$1" != "" ]; then
            source $1
        else
            printf "$BBLUE**$BWHITE Can't find PMBUILD [$BRED ERROR $BWHITE]\n$RESET"
        fi
    else
        source ./PMBUILD
    fi
     export buildroot=$(pwd)
    if [ -f $buildroot/$pkgname-$pkgver-$pkgrel.pkg.gz ]; then
        if [ "$1" != "-r" ]; then
            printf "$BBLUE**$BWHITE $pkgname-$pkgver-$pkgrel.pkg.gz already exists please use -r to rebuild [$YELLOW WARNING $BWHITE]\n$RESET"
            exit 0
        else
            [ -d pkg ] && rm -r pkg
            [ -d src ] && rm -r src
            [ -f $pkgname-$pkgver-$pkgrel.pkg.gz ] && rm -r $pkgname-$pkgver-$pkgrel.pkg.gz
        fi
    fi
    [ ! -d src ] && mkdir -p src
    [ ! -d pkg/$pkgname-$pkgver-$pkgrel.pkg ] && mkdir -p pkg/$pkgname-$pkgver-$pkgrel.pkg
    export pkgdir=$buildroot/pkg/$pkgname-$pkgver-$pkgrel.pkg
    if [ "$srcdir" = "" ]; then
        export srcdir=$buildroot/src/$pkgname
    fi
    if [ "$gitsource" != "" ]; then
        printf "$BBLUE**$BWHITE Downloading sources\n$RESET"
        git clone $gitsource $srcdir
        check $? "Download sources"
    fi
    if [ "$source" != "" ]; then
        printf "$BBLUE**$BWHITE Downloading sources\n$RESET"
        [ ! -d $srcdir ] && mkdir -p $srcdir
        cd $srcdir
        [ ! -f $pkgname-$pkgver.tar.* ] && wget $source
        cd - 
    fi
    if [[ $(type -t configure) = function ]]; then
        printf "$BBLUE**$BWHITE Configuring package\n$RESET"
        configure
        check $? "Configure"
    fi
    if [[ $(type -t build) = function ]]; then
        printf "$BBLUE**$BWHITE Building package\n$RESET"
        build
        check $? "Build"
    else
        echo "no build"
    fi
    if [[ $(type -t package) == function ]]; then
        printf "$BBLUE**$BWHITE Packaging package\n$RESET"
        package
        check $? "Package"
    else
        echo "no package"
    fi
    printf "$BBLUE**$BWHITE Stripping unneded symbols\n$RESET"
    for execfile in $(find $pkgdir -executable -type f); do
        strip $execfile
    done
    printf "$BBLUE**$BWHITE Strip unneded symbols [$BGREEN SUCCESS $BWHITE]\n$RESET"
    cd $pkgdir
    find -type f > $buildroot/list
    find -type l >> $buildroot/list
    sed -i "s/.\///" $buildroot/list
    sed -i 's/usr\/sbin//g' $buildroot/list
    sed -i 's/usr\/lib64//g' $buildroot/list
    sed -i 's/usr\/lib32//g' $buildroot/list
    cd $buildroot
    mv list $pkgdir/list
    if [ "$deps" != "" ]; then
        for i in $deps; do
            echo $i >> $pkgdir/deps
        done
    fi
    cd $pkgdir
    printf "$BBLUE**$BWHITE Archiving package\n$RESET"
    tar -czf $buildroot/$pkgname-$pkgver-$pkgrel.pkg.gz .. &> /dev/null
    check $? "Archive package"
    cd $buildroot
    unset pkgdir srcdir buildroot
}
#-----------------------------------------------------

#--- main ---
case "$1" in 
    add|a|del|d)
        checkroot
        "$1" $@
        ;;
    query|q|s|sync|clear|ss|search|list|l|unpack|u|down|download|deps)
        checkroot
        "$1" $2
        ;;
    build)
        buildpkg $2
        ;;
    *)
        help
        ;;
esac
#------------
