#!/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

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

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

# Load in colors and basic functions
source $TOOLPATH/util
source $TOOLPATH/dragoncolors

# 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
                                ;;
        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 )           gen=1
                                install=1
                                ;;
        f | flutter )           flutter=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
                                ;;
        only )                  only=1
                                ;;
        c | clean )             clean=1
                                ;;
        vn )                    NINJA_ARGS="-v"
                                ;;
        vd )                    export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
                                set -xv
                                ;;
        vg )                    export DGEN_DEBUG=1
                                ;;

        # --------
        # Commands
        # --------
        u | 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
                                ;;
        ch | checkra1n )        C1=$(which checkra1n) ||  prefix_print "Checkra1n is not currently installed. Exiting."; drexit 1
                                $C1 -g
                                drexit
                                ;;
        chc | checkra1ncli )    C1=$(which checkra1n) ||  prefix_print "Checkra1n is not currently installed. Exiting."; drexit 1
                                $C1 -c
                                drexit
                                ;;
        r | remote )            shift
                                remote $*
                                drexit
                                ;;
        relink )                rm -r "$DRAGON_DATA_DIR/sign/"
                                ;;
        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

# --------
# Build, then package (if needed)
# --------
if [[ $build -eq 1 ]]; then
    # shellcheck disable=SC2154
    # Invoke the generator
    if [[ $gen -eq 1 ]]; then
        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

    set -f
    # If there's more than one project in the root directory we need to iterate by name.
    # shellcheck disable=SC2207
    subsb=($(python3 -c "print('${project_dirs}' if ('${project_dirs}'.count('.')<2) else '${project_names}')"))
    set +f

    mkdir -p "$DRAGON_DATA_DIR"
    cp DragonMake "$DRAGON_DATA_DIR/DragonMake" 2> /dev/null

    for i in "${subsb[@]}"; 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
    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
