#!/usr/bin/env bash

export DRAGON_DIR=.dragon
export DRAGON_VERS=$(python3 -c 'from dragon.util import version; print(version())')

# Default dragon root dir is ~/.dragon
if [[ -z $DRAGON_ROOT_DIR ]]; then
    export DRAGON_ROOT_DIR=$HOME/$DRAGON_DIR
fi

TOOLPATH=$(python3 -c 'from dragon.util import tool_path; print(tool_path())')

# Load in basic functions
source $TOOLPATH/util

# Run setup wizard if dragon root dir is empty or nonexistent
if [[ -z "$(ls -A $DRAGON_ROOT_DIR 2> /dev/null)" ]]; then
    python3 -m dragon.wizard
    drexit 0
fi

# Check deps are good to go
source $TOOLPATH/prerun_checks

# Tool imports
source $TOOLPATH/simulator
source $TOOLPATH/packaging
source $TOOLPATH/building
source $TOOLPATH/generator
source $TOOLPATH/remote

# All "state" variables we set and then act upon.
source $TOOLPATH/variables

yaml() {
    python3 -c "import yaml;print(yaml.safe_load(open('$1'))$2)" 2> /dev/null
}

set -o pipefail

# Define the local dragon data dir
if [[ $PWD != $HOME ]]; then
    export DRAGON_DATA_DIR="$PWD/$DRAGON_DIR"
fi

# --------
# Argument Parsing
# Set a variable here or call a bash function if it's a tool
# --------

# If we have no args, print usage and exit
if [[ -z $1 ]]; then
    usage
    drexit
fi

while ! [[ -z $1 ]]; do
    case $1 in
        # --------
        # Set Variables
        # --------
        do )                    gen=1
                                build=1
                                install=1
                                ;;
        u | uninstall )         shift
                                uninstall_package $*
                                drexit
                                ;;
        g | gen | generate)     gen=1
                                ;;
        n | nic | new | edit | create )          python3 -m dragon.editor
                                drexit
                                ;;
        exp | export)           gen=1
                                exportt=1
                                build=1
                                ;;
        norm )                  norm=1
                                ;;
        b | build | make)       gen=1
                                build=1
                                ;;
        sim | simulator )       export simtarg=1
                                ;;
        i | install )           install=1
                                ;;
        debug )                 debug=1
                                shift
                                debugproc="$1"
                                ;;
        ddebug )                NINJA_ARGS="-v"
                                export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
                                set -xv
                                export DGEN_DEBUG=1
                                ;;
        c | clean )             gen=1
                                clean=1
                                ;;
        vn )                    NINJA_ARGS="-v"
                                ;;
        vd )                    export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
                                set -xv
                                ;;
        vg )                    export DGEN_DEBUG=1
                                ;;
        lo | objcs )            shift
                                python3 -m dragon.lo $*
                                drexit
                                ;;

        # --------
        # Commands
        # --------
        up | update | upgrade )            source $TOOLPATH/upgrader
                                drexit
                                ;;
        rs | respring )         python3 -m dragon.device run sbreload
                                drexit
                                ;;
        dr | devicerun )        shift
                                python3 -m dragon.device run $*
                                drexit
                                ;;
        s | device)             python3 -m dragon.device setup
                                ;;
        sr | rconf )            setupRemote
                                ;;
        sn | send )             send_package $2
                                drexit
                                ;;
        r | release )           release=1
                                ;;
        ro | rootless )         rootless=1
                                PkgPrefix="/var/jb"
                                ;;
        h | help | -h )         usage
                                drexit
                                ;;
        test )                  python3 -m dragon.test
                                drexit
                                ;;
        time )                  N=`date +%s%N`; export PS4='+[$(((`date +%s%N`-$N)/1000000))ms][${BASH_SOURCE}:${LINENO}]: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }';
                                set -x
                                ;;
        v | -v )                cat $DRAGON_ROOT_DIR/internal/banner.txt
                                ;;
        * )                     usage
                                drexit 1

    esac # who comes up with this syntax lol
    shift
done


# --------
# Generate project info
# --------
if [[ $gen -eq 1 ]]; then
    # Invoke the generator
    # shellcheck disable=SC2154
    rm -rf "$DRAGON_DATA_DIR/ninja/build.ninja" 2>/dev/null
    mkdir -p "$DRAGON_DATA_DIR/"{ninja,modules}

    generate

    if [[ $DRAGONGEN_FAILURE -eq 1 ]]; then
        cleanbuildfail
    fi
fi


get_subprojs()
{
    set -f
    # If there's more than one project in the root directory we need to iterate by name.
    # Relying on generator to obtain project info
    # shellcheck disable=SC2207
    subsb=($(python3 -c "print('${project_dirs}' if ('${project_dirs}'.count('.')<2) else '${project_names}')"))
    proj_names=($(python3 -c "print('${project_names}')"))
    set +f
    index=0
    for i in "${subsb[@]}"; do
        echo "$i ${proj_names[$index]}"
        ((index++))
    done
}


# --------
# Clean project(s)
# --------
if [[ $clean -eq 1 ]]; then
    # clean subproj build dir(s)
    get_subprojs | while read -r i j; do
        clean_dir $i $j
    done
    # ensure clean primary build dir
    clean_dir . $(basename $PWD)
fi


# --------
# Build, then package (if needed)
# --------
if [[ $build -eq 1 ]]; then
    mkdir -p "$DRAGON_DATA_DIR"
    cp DragonMake "$DRAGON_DATA_DIR/DragonMake" 2> /dev/null

    get_subprojs | while read -r i j; do
        # Copy the DragonMake into the subproject's build directory
        # Primarily for bundle filter gen, right now.
        if [[ -d $i ]]; then
            mkdir -p "$i/$DRAGON_DIR/"
            cp DragonMake "$i/$DRAGON_DIR/DragonMake" 2> /dev/null
        fi
        build $i $j
    done

    find . -name '.clean' -type f -delete

    if [[ $DRAGON_DPKG -eq 1 ]]; then
        create_package
    fi

    prefix_print "Cleaning Up"

    if [[ $norm -eq 0 ]]; then
        find . -name '*.ninja' -type f -delete
    fi
fi


# --------
# Install a package after building (doesn't need to be same session)
# DRAGON_DPKG is 1 by default, modified by the generator
# --------
if [[ $install -eq 1 && $DRAGON_DPKG -eq 1 ]]; then
    OUTPUT="$(cat "$DRAGON_DATA_DIR/last_package" | tr -d '\040\011\012\015' )"

    if [[ -z $OUTPUT ]]; then
        prefix_print "Packaging Failed"
        drexit
    fi

    send_package packages/$OUTPUT

    INSTALL_CMD=$(yaml DragonMake "['icmd']" || echo "sbreload")

    python3 -m dragon.device run ${INSTALL_CMD} || drexit
fi


# --------
# On-device debugging
# --------
if [[ $debug -eq 1 ]]; then
    eval $(python3 -m dragon.device get)
    prefix_print "Starting on device debugger and targeting '$debugproc'"
    ssh -p $DRBPORT root@$DRBIP "command -v lldb || apt install lldb" || drexit
    ssh -p $DRBPORT root@$DRBIP "lldb -n $debugproc || killall lldb" || drexit
fi


rm -rf "$DRAGON_DATA_DIR/packages" > /dev/null
set +xv

python3 -m dragon.update_check
