#!/bin/env fish
begin
    set -l dir (status dirname)

    set -l actions \
        install \
        installSW \
        configure \
        configureSW \
        userConfig \
        userConfig

    functions -e installSW
    functions -e configureSW
    functions -e userConfig

    function runPSUserAction -a script action name
        pwsh -CommandWithArgs '& $args[0] $args[1] @{ name=$args[2]; }' "$script" "$action" "$name"
    end

    function runPSUserConfig -a script name
        runPSUserAction "$script" ConfigureUser "$name"
    end

    function inherit -V actions -a script -d "Inherits the installer from the specified script."
        for i in (seq 1 2 (count $actions))
            set -l action $actions[$i]
            set -l functionName $actions[(math $i + 1)]
            set -l baseName $functionName"Base"

            function $baseName -V script -V action
                fish "$script" $action $argv
            end

            function $functionName -V baseName
                $baseName $argv
            end
        end
    end

    function runInstaller -V dir -a action
        set -l path (status stack-trace | head -n4 | tail -n1 | string replace --regex -- '^\s*called on line \d+ of file (.*)$' '$1')
        set -l name (basename (dirname $path))
        runInstallerAction $name $argv
    end

    function runInstallerAction -V dir -V actions
        argparse "force" -- $argv
        set -l install
        set -l args $_flag_force
        set -l name $argv[1]
        set -l action $argv[2]
        source "$dir/settings.fish"

        if [ -n "$_flag_force" ]
            set force true
        else
            set force false
        end

        if isProgramEnabled $name || $force
            set install true
        else
            set install false
        end

        if [ -z "$action" ]
            set action install
        end

        for i in (seq 1 2 (count $actions))
            if [ "$action" = "$actions[$i]" ]
                set -l message
                set -l function $actions[(math $i + 1)]
                set -l argv $argv[3..]
                set -l postRun "__postRun"
                functions -e $postRun

                switch "$action"
                    case install
                        set message "Installing `$name`..."

                        function $postRun -V args -V name
                            runInstallerAction $args $name configure

                            if not isConfigured || [ "$USER" != (getConfig "valhalla.setupUser.name") ]
                                runInstallerAction $args $name userConfig
                            end
                        end
                    case configure
                        set message "Configuring `$name`..."
                    case userConfig
                        set -l user $argv[1]
                        set argv $argv[2..]

                        if [ -z "$user" ]
                            set user "$USER"
                        end

                        if isProgramEnabled "$name" "$user" || $force
                            set install true
                        else
                            set install false
                        end

                        set message "Configuring `$name` for `$user`..."
                end

                if functions -q "$function" && $install
                    if [ -n "$message" ]
                        echo $message
                    end

                    "$function" $argv
                end

                if functions -q $postRun
                    $postRun
                end
            end
        end
    end
end