#!/bin/sh
set -e
required="awk ssh git hostname basename"
test -z $HOST && host=$USER@$(hostname) || host=$HOST
RECIPE_REPOS="https://raw.githubusercontent.com/coderofsalvation/podi/master/recipe/.index.txt"
#trap "trigger cleanup" 0 1 2 3 6
C_GREY="\\033[1;30m"
C_BOLD="\\033[1;37;40m"
C_NORMAL="\\033[0;0m"
C_CYAN="\\033[1;36m"
C_PURPLE="\\033[38;5;207m"
C_RED="\\033[0;31m"

# some hipster wrappers to make things readable and sexy later on
extract()    { awk '/^# '$1':/ { gsub("^# '$1': ","",$0); print $0 }' $0; }
try()        { set +e; "$@"; set -e; return 0;     }
silent()     { "$@" 1>/dev/null 2>/dev/null;       }
installed()  { which $1 2>/dev/null 1>/dev/null;   }
error()      { printf " [$C_RED"e"$C_NORMAL] %s\n" "$*"; exit 1; }
print()      { printf "  $C_PURPLE│ $C_NORMAL %s\n" "$*"; }
header()     { h=$1; shift; printf "  $C_PURPLE├─ $C_CYAN""%s""$C_PURPLE $C_NORMAL%s\n" "$h" "$*"; }
evalfunc()   { type $1 | awk 'NR>2 && /^[^{][^}]/ { print $0 }'; }
foreach()    { local err=0; local args="$1"; 
               shift; 
               for j in $args; do "$@" "$j" || err=1; done
               test $err = 1 && return 1 || return 0
             }
trigger()    { printf "$C_BOLD%-25s $C_NORMAL[$C_CYAN✓$C_NORMAL] ($C_GREY%s)$C_NORMAL\n" "$(test $host = $USER@$(hostname) && printf $1 || printf "  | $1")" $host 1>&2
               local cmd=$1; shift
               local actions="$(eval echo \$on_$cmd)"
               if test -n "$actions"; then 
                 silent try type $cmd && { $cmd "$@"; }
                 for it in $actions; do trigger $it "$@"; done 
               else 
                 silent type $cmd || return 0; 
                 silent type $cmd && $cmd "$@"; 
               fi 
             }
on()         { export on_$1="$2 $(eval echo \$on_$1)"; }

# pipeline: deploy(){
# pipeline:   trigger hello
# pipeline:   trigger backup
# pipeline:   trigger checkout 
# pipeline:   trigger build
# pipeline:   trigger runtests
# pipeline:   trigger start
# pipeline: }
# pipeline: 
# pipeline: checkout(){
# pipeline:   git --work-tree=$(pwd) --git-dir=$(pwd)/.git checkout -f
# pipeline: }

init_post_receive(){
  echo "#!/bin/sh
    export PM_REMOTE=$2
    export PM_USER=$3
    export PM_PORT=$4
    export PM_APP=$(basename $(pwd))
    export PM_COMMIT=\$(git --work-tree=$1 --git-dir=$1/.git log -n1 --pretty=format:\"%h\")
    cd $1
    mkdir .tmp
    git --work-tree=$1/.tmp --git-dir=$1/.git checkout -f
    test -f .tmp/podi && {
      test -f podi  && rm podi
      test -d .pod && rm -rf .pod
      cp -r .tmp/podi .tmp/.pod .
    }
    rm -rf .tmp
    test -f podi && ./podi deploy 
  " | awk '{ gsub("^[ ]+","",$0); print $0 }'
}

loadremote(){
  cfg=.pod/$1/$2/config
  test -f $cfg || error "remote (.pod/$1/$2/config) does not exist"
  . $cfg
}

hello(){
  echo -e '
\e[38;5;57m                                     88  88  
\e[38;5;93m                                     88      
\e[38;5;129m  8b,dPPYba,    ,adPPYba,    ,adPPYb,88  88  
\e[38;5;165m  88P`    "8a  a8"     "8a  a8"    `Y88  88  
\e[0m  88       d8  8b       d8  8b       88  88  
\e[38;5;201m  88b,   ,a8"  "8a,   ,a8"  "8a,   ,d88  88  
\e[38;5;201m  88`YbbdP"`    `"YbbdP"`    `"8bbdP"Y8  88  
\e[38;5;205m  88                                         
\e[38;5;207m  88                                         
\e[0m'
}

init(){ # init git@server:/dir/to/deploy [branch] [port] [name] : initializes a deployment 
  test -z $1 && usage 
  trigger init_localhost
  trigger init_server "$@"
}

init_localhost(){
  test -d ~/.pod || { mkdir -p ~/.pod && extract config   > ~/.pod/config; }
  test -d .pod   || { 
    mkdir -p .pod  && extract pipeline > .pod/pipeline; 
    test -d   .pod && for i in .pod/*  ; do . $i; done 
    test -f podi || cp $0 .
  }
}

# <user@server:path> [branch] [port]
init_server(){
  user=$(    echo $1 | awk '{ gsub("@.*","",$0); print $0 }')
  server=$(  echo $1 | awk '{ gsub(".*@","",$0); gsub(":.*","",$0); print $0 }')
  gitpath=$( echo $1 | awk '{ gsub(".*:","",$0); print $0 }')
  appname=$(basename $gitpath)
  test -z $2 && branch=$(git branch | awk '/^\*/ { print $2 }') || branch=$2
  test -z $3 && port=22 || port=$3
  mkdir -p .pod/$user@$server
  local config=.pod/$user@$server/$appname/config
  mkdir -p $(dirname $config)
  echo "export server='$server'                      " >  $config
  echo "export port='$port'                          " >> $config
  echo "export user='$user'                          " >> $config
  echo "export gitpath='$gitpath'                    " >> $config
  echo "export appname='$appname'                    " >> $config
  echo "export branch='$branch'                      " >> $config
  . $config 
  ssh -p $port $user@$server HOST=$user@$server mkdir $gitpath
  scp -r -P $port $0 .pod $user@$server:$gitpath/. 1>/dev/null
  try ssh -p $port $user@$server HOST=$user@$server "cd $gitpath; ./podi init_gitops $gitpath $server $user $port"
  test -d .git || git init
  git remote | silent grep $appname || git remote add -t $branch $appname ssh://$user@$server:$port$gitpath/.git
  silent git push $appname $branch 
  print "you can now run: git push $gitremote $branch"
  export PM_SERVER=$server 
  export PM_BRANCH=$branch
}

# <path> <server> <user> <port>
init_gitops(){
  git --version 1>/dev/null 2>/dev/null || error please install git on $server 
  test -d $1 || mkdir $1
  test -d $1/.git && printf "already initialized: $C_GREY$1/.git$C_NORMAL\n"
  test -d $1/.git || {
    silent git init --bare "$1/.git" || error could not create $1/.git
  }
  trigger init_post_receive $1 $2 $3 $4 > $1/.git/hooks/post-receive
  chmod +x $1/.git/hooks/post-receive
}

recipe(){ # recipe <name_or_url> : installs a recipe from podi repo or url
  list(){
    for repo in $RECIPE_REPOS; do 
      print $(dirname $repo)
      curl $repo
    done
  }
  install(){
    for repo in $RECIPE_REPOS; do 
      curl $repo | grep -E "^$1$" && {
        test -d .pod || mkdir .pod
        print "installing $1 from $(dirname $repo)"
        curl $(dirname $repo)/$1 > .pod/$1
      }
    done
  }
  init_localhost
  test -z $1 && list
  test -z $1 || install $1
  "$@"
}

usage(){
  echo "usage: "
  awk '/[a-zA-Z0-9_]+\(\){ #/ { 
    info=$0 
    gsub(".* : ","",info)
    gsub(".*{ # ","",$0)
    gsub(" :.*","",$0)
    printf("    %-55s %s\n",$0,info)
  }' $0 .pod/* 2>/dev/null
  printf "\ndeploy targets:\n"
  git remote | awk '{ printf("   %s\n",$1) }'
  exit 0
}

foreach "$required" installed || error "please install: $required" 
# source external variables, functions and decorators 
test -d  .pod && for i in $(find .pod -type f); do . $i; done 
test -z $1 && usage
trigger "$@"
