#!/usr/bin/env bash
###
### arching-kaos-tools
### Tools to interact and build an Arching Kaos Infochain
### Copyright (C) 2021 - 2025  kaotisk
###
### 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 program 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/>.
###
export AK_DEBUG="yes"
##
## Arching Kaos CLI tool is the main executable script to use for exploring,
## creating and distributing local blockchain(s) called zchain(s).
##
## It is accompanied with several utilities that help to create new blocks,
## reference them, export blocks to HTML pages, "roll-back" your zchain to an
## older block, reset your zchain and more.
##
## Run with no arguments to see available commands
##
##    -h, --help                  Prints this help message
##
##    -m, --module [module]       Run a specified module. If no module provided
##                                the list of available modules will be printed.
##
##    [command] [args]            Run a command. If none provided a list of
##                                commands will be printed.
##
fullprogrampath="$(realpath $0)"
PROGRAM="$(basename $0)"
descriptionString="Arching Kaos CLI"

source $HOME/.arching-kaos/rc
source $AK_LIBDIR/_ak_log
source $AK_LIBDIR/_ak_script

if [ $# -eq 0 ]
then
    _ak_log_warning "No command given"
    _ak_log_info "Available commands:"
    (
        find $AK_BINDIR | grep 'ak-' | while read available
        do
            #subcmd="$(basename $available | cut -d '-' -f 2)"
            subcmd="$(basename $available)"
            args="-h"
            if [ -n "$subcmd" ]
            then
                echo $subcmd | cut -d '-' -f 2 | sort | uniq | sed -e 's/^/ak /g'
                #$(echo $subcmd) $args
            fi
        done
    ) | sort | uniq | sed 's/^/# /g' | while read line; do _ak_log_info "$line";done
    exit 1
fi

if [ $# -eq 1 ]
then
    case "$1" in
        -h|--help)
            _ak_usage
            exit 1
            ;;
        -v|--version)
            _ak_version
            exit 1
            ;;
    esac
fi

if [ ! -n "$(echo -n $1 | sed 's/[0-9]//g')" ] && [ "$(( $(echo -n $1 | xxd -p) - 2100))" == "1337" ]
then
    AK_DEBUG="no"
    echo -n efb8bbe294b3e383863de4b880 | xxd -r -p
fi

subcmd="$(echo $* | sed -e 's/ /-/g')"

case "$1" in
    -f|--function)
        shift
        if [ ! -z $1 ] && [ -n "$1" ]
        then
            grep -rnF "$1(){" $AK_BINDIR/* $AK_LIBDIR/* $AK_MODULESDIR/* > /dev/null 2>&1
            if [ $? -ne 0 ]
            then
                _ak_log_error "No function $1 found"
                exit 1
            fi
            if [ $(grep -rnF "$1(){" $AK_LIBDIR/* $AK_MODULESDIR/* | wc -l) -gt 1 ]
            then
                _ak_log_error "More than one functions found with name $1"
                exit 1
            fi
            filename="$(grep -rnF "$1(){" $AK_LIBDIR/* $AK_MODULESDIR/* | cut -d ':' -f 1)"
            line="$(grep -rnF "$1(){" $AK_LIBDIR/* $AK_MODULESDIR/* | cut -d ':' -f 2)"
            functionname="$(grep -rnF "$1(){" $AK_LIBDIR/* $AK_MODULESDIR/* | cut -d ':' -f 3|sed -e 's/function //g')"
            _ak_log_info "Use with:"
            printf 'source %s\n%s\n' "$filename" "$(echo -n $functionname | sed 's/(){//')"
            exit
        else
            _ak_log_error "No function selected"
            _ak_log_info "Available functions:"
            grep -rnF "(){" $AK_LIBDIR/* $AK_MODULESDIR/* | \
                sed -e "s#$AK_WORKDIR/##g" | \
                sed -e 's/function //g;s/(){//g' | \
                cut -d ':' -f 1,3 | \
                tr ':' ' ' | \
                awk '{print $1 " " $2}' | \
                sort | while read line; do _ak_log_info "${line}"; done
            exit
        fi
        ;;


    # Add functionality for separate modules directory
    -m|--module)
        shift
        subcmd="$AK_MODULESDIR/$(echo $1 | sed -e 's/ /-/g')"
        if [ ! -n "$1" ]
        then
            _ak_log_error "No module selected"
            _ak_log_info "Modules available:"
            ls -1 $AK_MODULESDIR | sed 's/^/# /g' | while read line; do _ak_log_info "$line";done
            exit 1
        fi
        shift
        subargs="$*"
        if [ ! -n $subargs ]
        then
            subargs="--help"
        fi
        if [ ! -f $subcmd/main.sh ]
        then
            _ak_log_error "No $(basename $subcmd) module"
            exit 1
        fi
        $subcmd/main.sh $subargs
        _ak_exit_program $? "$subcmd module finished";
        ;;
esac

if [ -f "$AK_BINDIR/ak-$subcmd" ]
then
    $(echo ak-$subcmd)
    _ak_exit_program $? "ak-$subcmd command finished";
else
    argc=$#
    argv="$*"
    counter=1
    while [ $counter -lt $argc ]
    do
        subcmd="$(echo $argv | cut -d ' ' -f -$counter | sed -e 's/ /\-/g')"
        args="$(echo "$argv"| cut -d ' ' -f $(($counter + 1))-)"
        if [ -n "$subcmd" ] && [ -f "$AK_BINDIR/ak-$subcmd" ]
        then
            _ak_log_info "Running: ak-$subcmd with args: $args"
            $(echo ak-$subcmd) $args
            _ak_exit_program $? "ak-$subcmd command finished";
        fi
        counter=$(($counter + 1))
    done
    find $AK_BINDIR | while read available
    do
        echo $(basename $available) |\
            grep ak-$(echo $argv | cut -d ' ' -f 1) |\
            sed -e 's/-/ /g'
    done
    _ak_log_error "Unknown subcommand: $*"
    exit 1
fi