<?php
namespace BitFirePlugin;


use BitFire\Abuse;
use BitFire\BitFire;
use BitFire\Config as CFG;
use Exception;
use RuntimeException;
use ThreadFin\CacheItem;
use ThreadFin\Effect as Effect;
use ThreadFin\FileData;
use ThreadFin\FileMod;

use const BitFire\BITFIRE_VER;
use const BitFire\BOT_ALLOW_AUTH;
use const BitFire\CACHE_HIGH;
use const BitFire\FILE_RW;
use const BitFire\FILE_W;
use const BitFire\INFO;
use const BitFire\WAF_ROOT;
use const BitFire\WAF_SRC;
use const ThreadFin\DAY;

use function BitFire\is_admin;
use function BitFireSvr\bf_activation_effect;
use function BitFireSvr\update_config;
use function BitFireSvr\update_ini_value;
use function ThreadFin\contains;
use function ThreadFin\file_recurse;
use function ThreadFin\dbg;
use function ThreadFin\en_json;
use function ThreadFin\trace;
use function ThreadFin\debug;
use function ThreadFin\ends_with;
use function ThreadFin\error;
use function ThreadFin\get_hidden_file;
use function ThreadFin\HTTP\http2;
use function ThreadFin\httpp;
use function ThreadFin\partial as ƒixl;
use function ThreadFin\partial;
use function ThreadFin\partial_right as ƒixr;
use function ThreadFin\path_to_slug;
use function ThreadFin\random_str;
use function ThreadFin\ƒ_id;
use function ThreadFin\ƒ_inc;

#define FLUSH_RX 0xE1
#define FLUSH_TX 0xE2
#define REUSE_TX_PL 0xE3
#define R_RX_PL_WID 0x60
#define W_ACK_PAYLOAD 0xA9
#define W_TX_PAYLOAD_NOACK 0xB0
#define NOP 0xFF


// we should have attempted load 2x before here
// 1: for for auto load, 2: plugin load, if it didn't load, something is wrong
if (!defined("BitFire\\WAF_ROOT")) {
    echo "<p>BitFire did not load correctly. Please re-install.</p>\n";
    return;
}



/**
 * @OVERRIDE dashboard url
 * @since 1.9.0 
 */
function dashboard_url(string $page_name) : string {
    $url = \admin_url("admin.php?page=$page_name");
    return $url;
}



/**
 * Register a custom admin menu page.
 */
function bitfire_add_menu() {
    $alerts = create_plugin_alerts();
    $slug = "bitfire";

    \add_menu_page(
        "BitFire Dashboard",
        "BitFire",// <span class='update-plugins count-$base_num' title='$title'><span class='plugin-count'>$base_num</span></span>",
        "manage_options",
        $slug,
        "\BitFire\serve_dashboard",
        "dashicons-shield",
        66
    );

    \add_submenu_page(
        $slug,
        "BitFire Dashboard",
        "Dashboard",
        "manage_options",
        $slug,
        "\BitFire\serve_dashboard",
        0
    );


    \add_submenu_page(
        $slug,
        "BitFire Bot Control",
        "Bot Control",
        "manage_options",
        "bitfire_botlist",
        "\BitFire\serve_bot_list",
        1
    );

    \add_submenu_page(
        $slug,
        "BitFire Settings",
        "Settings",
        "manage_options",
        "bitfire_settings",
        "\BitFire\serve_settings",
        2
    );
    
    \add_submenu_page(
        $slug,
        "BitFire Malware Scanner",
        "Malware Scan",
        "manage_options",
        "bitfire_malware",
        "\BitFire\serve_malware",
        3
    );  

    \add_submenu_page(
        $slug,
        "BitFire Exceptions",
        "Rule Tune / IP Block",
        "manage_options",
        "bitfire_exceptions",
        "\BitFire\serve_exceptions",
        4
    ); 

    
}



// helper wrapper for wp_enqueue_script
function add_script_src(string $handle, string $src, string $optional) : string {
    if (contains($src, "https")) {
        \wp_enqueue_scripts($handle, $src, [], "1.0", true);
    }
    return "";
}

// helper wrapper for wp_add_inline_script
function add_script_inline(string $handle, string $code) : string {
    \wp_add_inline_script($handle, $code);
    return "";
}

function bitfire_styles() {

    if (stristr($_SERVER['REQUEST_URI'], "wp-admin/plugins.php") !== false) {
        //\wp_register_script("bitfire", plugin_dir_url(__FILE__) . "public/plugin-monitor.js", ["jquery"], "1.1", true);
        //\wp_enqueue_script("bitfire", plugin_dir_url(__FILE__) . "public/plugin-monitor.js", "1.1", false);
    }


    // ONLY ENQUEUE ON BITFIRE PAGES
    $page = filter_input(INPUT_GET, "BITFIRE_WP_PAGE", FILTER_SANITIZE_SPECIAL_CHARS);
    if (empty($page)) {
        $page = filter_input(INPUT_GET, "page", FILTER_SANITIZE_SPECIAL_CHARS);
        if (empty($page) || !contains($page, "bitfire")) {
            return;
        }
    }

    \wp_register_script("dashkit", plugin_dir_url(__FILE__) . "public/dashkit.min.js", ["jquery"], "1.0", true);
    \wp_register_script("dashkit-chart", plugin_dir_url(__FILE__) . "public/chart.min.js", ["jquery"], "1.0", true);
    \wp_register_script("dashkit-diff", plugin_dir_url(__FILE__) . "public/difflib.js", ["jquery"], "2.0", true);
    \wp_register_script("dashkit-prism", plugin_dir_url(__FILE__) . "public/prism.js", ["jquery"], "2.0", true);
    \wp_register_script("dashkit-internal", plugin_dir_url(__FILE__) . "public/internal.js", [], "2.3", false);
    \wp_register_script("dashkit-vendor", plugin_dir_url(__FILE__) . "public/vendor.bundle.js", ["jquery"], "1.0", true);
    \wp_register_script("dashkit-theme", plugin_dir_url(__FILE__) . "public/theme.bundle.js", ["jquery"], "1.0", true);
    \wp_register_script("dashkit-pako", plugin_dir_url(__FILE__) . "public/pako.js", [], "1.0", true);
    //\wp_register_script("dashkit-underscore", plugin_dir_url(__FILE__) . "public/underscore.min.js", [], "1.0", false);
    \wp_register_style("dashkit-vs2015", plugin_dir_url(__FILE__) . "public/vs2015.min.css", [], "1.0");
    \wp_register_style("dashkit-prism", plugin_dir_url(__FILE__) . "public/prism.css", [], "1.0");
    //\wp_register_style("dashkit-theme", plugin_dir_url(__FILE__) . "public/theme.min.css", [], "1.0");
    \wp_register_style("dashkit-bundle", plugin_dir_url(__FILE__) . "public/theme.bundle.css", [], "1.0");
    \wp_register_style("dashkit-feather", plugin_dir_url(__FILE__) . "public/feather.css", [], "1.0");
    \wp_register_script("bitfire", plugin_dir_url(__FILE__) . "public/bitfire_core.js", ["jquery"], BITFIRE_VER, false);

    //\wp_register_script("underscore2", "/wp-includes/js/underscore.min.js", [], false, false);
    \wp_enqueue_script("underscore");
    \wp_enqueue_script("dashkit-chart", plugin_dir_url(__FILE__) . "public/chart.min.js", ["jquery"], "1.0", false);
    \wp_enqueue_script("dashkit-vendor", plugin_dir_url(__FILE__) . "public/vendor.bundle.js", ["jquery"], "1.0", true);
    \wp_enqueue_script("dashkit-diff", plugin_dir_url(__FILE__) . "public/difflib.js", ["jquery"], "2.0", true);
    \wp_enqueue_script("dashkit-prism", plugin_dir_url(__FILE__) . "public/prism.js", ["jquery"], "2.0", true);
    \wp_enqueue_script("dashkit-internal", plugin_dir_url(__FILE__) . "public/internal.js", [], "2.3", false);
    \wp_enqueue_script("dashkit-pako", plugin_dir_url(__FILE__) . "public/pako.js", [], "1.0", true);
    \wp_enqueue_script("dashkit-theme", plugin_dir_url(__FILE__) . "public/theme.bundle.js", ["jquery"], "1.0", true);
    \wp_enqueue_script("dashkit", plugin_dir_url(__FILE__) . "public/dashkit.min.js", ["jquery"], "1.0", true);

    \wp_enqueue_style("dashkit-vs2015", plugin_dir_url(__FILE__) . "public/vs2015.min.css", [], "1.0");
    \wp_enqueue_style("dashkit-prism", plugin_dir_url(__FILE__) . "public/prism.css", [], "1.0");
    \wp_enqueue_style("dashkit-bundle", plugin_dir_url(__FILE__) . "public/theme.bundle.css", [], "1.0");
    \wp_enqueue_style("dashkit-feather", plugin_dir_url(__FILE__) . "public/feather.css", [], "1.0");

    \wp_enqueue_script("bitfire", plugin_dir_url(__FILE__) . "public/bitfire_core.js", BITFIRE_VER, false);
}

/**
 * called on user edit to update the mfa number
 * @param mixed $user_id - user id to update
 * @param int $number - will pull from post data if default or 0
 */
function user_edit($user_id, $number = 0) {
    if ($number == 0) {
        $number = filter_input(INPUT_POST, "bitfire_mfa_tel", FILTER_SANITIZE_SPECIAL_CHARS);
    }
    if ($number) {
        //$code = mt_rand(1, 9) . mt_rand(0, 9) . mt_rand(0, 9) . " " . mt_rand(1, 9) . mt_rand(0, 9) . mt_rand(0, 9);
        $code = random_str(24);
        update_user_meta($user_id, "bitfire_mfa_code", $code);
        update_user_meta($user_id, "bitfire_mfa_tel", $number);
    } else {
        debug("unable to edit user, no number given");
    }
}


/**
 * this function will also update the ignore cve data
 * @param bool $skip_ignored 
 * @return array 
 * @throws RuntimeException 
 * @throws Exception 
 */
function create_plugin_alerts($skip_ignored = true) : array {

    $result = [];

    $content_dir = CFG::str("cms_content_dir");
    if (!file_exists($content_dir) && defined(WP_CONTENT_DIR)) {
        $content_dir = WP_CONTENT_DIR;
    }
    // fetch the list of plugins with security issues
    $cve_plugins_file = $content_dir."/plugins/bitfire/data/plugins.json";
    if ($cve_plugins_file == "/plugins/bitfire/data/plugins.json") {
        return $result;
    }
    $file_data = FileData::create($cve_plugins_file);

    if (!$file_data->exists) {
        bitfire_plugin_check();
    }
    if($file_data->exists) {
        $plugins = json_decode($file_data->read()->raw(), true);
        // update ignore data if user is an admin
        if (isset($_GET['cve_ignore']) && is_admin()) {
            $match_fn = function($key, $value) { return $value['cve'] == $_GET['cve_ignore']; };
            /*
            TODO: MATCH FUNCTION NEEDS IMPLEMENTATION
            $plugins = \BitfirePlugin\array_filter_modify($plugins,
                $match_fn,
                function($key, $value) { $value['ignore'] = time() + \ThreadFin\DAY; return $value; }
            );
            */
            $file_mod = new FileMod($cve_plugins_file, en_json($plugins), FILE_RW);
            Effect::create()->file($file_mod)->run();
        }
        // no plugins found?  odd...
        if (empty($plugins)) { return $result; }

        //global $wp;
        //$self = add_query_arg($wp->query_vars, home_url($wp->request));
        $self = preg_replace("/[?&]cve_ignore=[^&]*/", "", $_SERVER['REQUEST_URI']);
        $self .= ((strpos($self, "?") === false) ? "?" : "&");

        foreach ($plugins as $plugin) {
            $name = esc_html(strtolower($plugin["name"]));
            // skip if we have already ignored this plugin
            if ($skip_ignored && $plugin['ignore']??0 > time()) { continue; }

            if (strlen($plugin["vendor"])) {
                $vendor = esc_html(strtolower($plugin["vendor"]));
                $name = "<a href='/wp-admin/plugins.php#{$name}-update'>$name</a> by " . $vendor;
            }
            if (!strlen($name) > 3) { $name = esc_html(strtolower($plugin["plugin_name"]));}
            $cve = esc_html($plugin["cve"]??"unknown");


            $links = array_reduce(explode("\n", $plugin["links"]), function($carry, $item) {
                $item = esc_html($item);
                return $carry . " <a style='float:left' href='$item' target='_blank'>$item</a><br>";
            }, "");
            $difficulty = esc_html($plugin["difficulty"]??"unknown");
            $type = esc_html($plugin["cvss_type"]??"unknown");
            $info = esc_html($plugin["info"]??"unknown");
            $result[] = "<style>.bf{height:0;line-height:0;padding:0;overflow:hidden;opacity:0;transition:all .5s ease-in-out;} .bf.open{padding:.5em;line-height:1.5;opacity:1;height:auto !important}</style>
            <strong>$name has a known security issue <a target='_blank' href='https://cve.mitre.org/cgi-bin/cvename.cgi?name=$cve'>$cve</a></strong> <span style='padding-left:3rem'>Exploit difficulty: <em>".
            "{$difficulty}</em></span><br><hr>{$type}<span style='float:right;display:none;' class='dashicons dashicons-arrow-up' onclick='document.getElementById(\"bf-slide{$cve}\").classList.toggle(\"open\")'></span><br><hr><div class='bf open' id='bf-slide{$cve}'>{$info}<br><br>$links<a style='text-align:right;width:100%;display:block;margin-bottom:1rem;' href='{$self}cve_ignore=$cve' title='hide this alert for 1 day'>Dismiss Notice</a></div>";//, $plugin["plugin_name"]); 
        }
    }

    return $result;
}


/**
 * add admin notices for disabled configurations
 * @return void 
 */
function alerts() {

    return;
    
    // permanently disable nag messages  
    if (isset($_GET['bitfire_nag_ignore'])) { \BitFireSvr\update_ini_value("nag_ignore", "true")->run(); return; }
    if (strpos($_SERVER['REQUEST_URI'], "plugins.php") > 1) {
       \ThreadFin\do_for_each(create_plugin_alerts(), ƒixl("BitFirePlugin\show_alert", "error"));
    }

    
    // honor disable nag notices
    if (defined("DISABLE_NAG_NOTICES") && DISABLE_NAG_NOTICES) { return; }
    // notice has been dismissed
    if (CFG::enabled("nag_ignore")) { return; }

    $current_url = filter_input(INPUT_SERVER, "REQUEST_URI", FILTER_SANITIZE_SPECIAL_CHARS);
    $current_url .= (strpos($current_url, "?") > 1) ? "&" : "?";

    // show some nag notices for important settings
    if (CFG::disabled("whitelist_enable") || CFG::disabled("require_full_browser")) {
        $url = admin_url("admin.php?page=bitfire_settings#bot_handling");
        show_alert("warning", "<div style='display:flex;flex-direction:row;justify-content:space-between;'><span><a href='$url'>BitFire Settings</a> : Bot blocking is not fully enabled.  Please enable <strong>whitelist</strong> and <strong>full browser required</strong> to block hacking bots.</span> <a href='{$current_url}bitfire_nag_ignore=1'>&#10006; Dismiss</a></div>");
    }
    /*
    if (CFG::disabled("auto_start")) {
        $url = admin_url("admin.php?page=bitfire_settings");
        show_alert("warning", "<div style='display:flex;flex-direction:row;justify-content:space-between;'><span><a href='$url'>BitFire Settings</a> : <strong>Always-On protection</strong> needs to be enabled to prevent direct plugin attacks. </span> <a href='{$current_url}bitfire_nag_ignore=1'>&#10006; Dismiss</a></div>");
    }
    */
    if (strlen(CFG::str("pro_key")) > 20) {
        if (CFG::disabled("rasp_filesystem")) {
            $url = admin_url("admin.php?page=bitfire_settings");
            //show_alert("warning", "BitFire File Lock is purchased but disabled.  Please enable in BitFire Advanced Settings");
            show_alert("warning", "<div style='display:flex;flex-direction:row;justify-content:space-between;'><span><a href='$url'>BitFire Advanced</a> : BitFire File Lock is purchased but disabled.  Please enable in BitFire Advanced Settings. </span> <a href='{$current_url}bitfire_nag_ignore=1'>&#10006; Dismiss</a></div>");
        }
    }
}

/**
 * echo an alert
 * @param string $type  (warning|error|success|info)
 * @param string $notice 
 */
function show_alert(string $type, string $notice, string $id="") {
    if ($id != "") {
        echo "<div data-dismissible='$id-1' class='notice notice-{$type} is-dismissible'><p>{$notice}</p></div>\n";
    } else {
        echo "<div data-dismissible='disable-done-notice-forever' class='notice notice-{$type}'>{$notice}</div>\n";
    }
}



function user_columns($columns = []) {
    if (is_admin()) {
        //$columns['bitfire_mfa'] = "BitFire MFA";
        $columns['bitfire_last_login'] = "BitFire Last Login";
    }
    return $columns;
}

//function custom_columns() {
function custom_columns($value = '', $column_name = '', $user_id = 0) {
    switch($column_name) {
        case "bitfire_last_login":
            $last_login = get_user_meta($user_id, "bitfire_last_login", true);
            $parts = explode(":", $last_login);
            if ($last_login) {
                $days_ago = floor((time() - intval($parts[0])) / DAY);
                if ($days_ago > 365) { $days_ago = ">365"; }
                return "{$days_ago} days ago {$parts[5]}<br>" . join("/", array_slice($parts, 1, 4));
            } else {
                return "Never";
            }
            break;
        case "bitfire_mfa":
            $mfa = get_user_meta($user_id, "bitfire_mfa_tel", true);
            $correct = intval(get_user_meta($user_id, "bitfire_mfa_correct", true)||0);
            $sent = intval(get_user_meta($user_id, "bitfire_mfa_sent", true)||0);
            $edit_url = _wp_specialchars(get_admin_url() . "user-edit.php?user_id={$user_id}#bitfire_mfa", ENT_QUOTES);

            $html = ($mfa) ? 
            "<a href='$edit_url'><span class='dashicons dashicons-yes' data-code='f12a'></span><span style='color:#181;text-decoration:underline' title='Click to edit the MFA telephone number'>Yes</span></a>&nbsp;&nbsp;&nbsp;<span style='color:#999'> ok: </span><strong>$correct</strong> / <strong>$sent</strong>"
            : "<a href='$edit_url'><span class='dashicons dashicons-no' data-code='f158'></span><span style='color:#181;text-decoration:underline' title='Click to edit the MFA telephone number'>No</span></a>";
            return $html;
    }
}




/**
 * todo: re-implement
 */
function bitfire_plugin_check() {
    @include_once WAF_ROOT . "includes.php";
    $all_dirs = malware_scan_dirs(CFG::str("cms_content"));

    $plugins = [];
    foreach ($all_dirs as $dir) {
        if (contains($dir, ["wp-includes", "wp-admin"])) { continue; }
        $plugin = basename($dir);
        $file = FileData::create("{$dir}/readme.txt")->read()->filter(ƒixr("\ThreadFin\icontains", "Stable Tag"));
        $line = implode(" ", $file->lines);
        $parts = explode(":", $line);
        if (isset($parts[1])) {
            $plugins[$plugin] = trim($parts[1]);
        } else {
            file_recurse($dir, function ($x) use (&$plugins, $plugin) {
                $file = FileData::create($x)->read()->filter(ƒixr("\ThreadFin\icontains", " Version: "));
                if (!empty($file->lines)) {
                    $line = implode(" ", $file->lines);
                    $parts = explode(":", $line);
                    $plugins[$plugin] = trim($parts[1]);
                    return true;
                }
                return false;
            }, "/.*.php/", [], 1); 
        }
    }

    $encoded = base64_encode(en_json($plugins));
    require_once WAF_SRC . "http.php";
    $result = http2("POST", "https://cve.bitfire.co/cve_check.php", $encoded, ["Content-Type: application/json"]);
    $content_dir = CFG::str("cms_content_dir");
    if (!file_exists($content_dir)) {
        if (defined(WP_CONTENT_DIR)) {
            $content_dir = WP_CONTENT_DIR;
        } else {
            $content_dir = dirname(__DIR__, 3);
        }
    }
    $effect = Effect::create()->file(new FileMod($content_dir."/plugins/bitfire/data/plugins.json", $result->content, FILE_RW));
    $effect->run();
}



/**
 * update our fast plugin to ID mapping for error tracking
 * @return Effect 
 */
function update_plugin_list(): Effect {
    $result = new Effect();
    $target   = __DIR__ . '/plugin_mapping.php';
    if (file_exists($target)) {
        if ((time() - filemtime($target)) < 600) {
            return $result; // only update once 10 min
        }
        include_once $target; // load existing map if it exists
    }

    $plugins = glob(WP_CONTENT_DIR . '/plugins/*/'); // Get all plugin directories
    $map     = [];
    $i       = 1;
    sort($plugins);

    foreach ($plugins as $plugin_file) {
        // slug is top-level directory, or filename without .php if in root
        $slug = path_to_slug($plugin_file);

        if (!isset($map[$slug])) {          // keep first occurrence if duplicates
            $map[$slug] = $i++;
        }
    }

    // nothings has changed, dont update the file
    if (defined("BITFIRE_PLUGIN_MAP") && is_array(BITFIRE_PLUGIN_MAP)) {
        $diff = array_diff($map, BITFIRE_PLUGIN_MAP ?? []); // only update if changed
        if (count($diff) == 0) {
            return $result;
        }
    }

    $code = "<?php\n"
          . "/** generated: " . date('c') . " */\n"
          . "if (!defined('BITFIRE_PLUGIN_MAP')) {\n"
          . "    define('BITFIRE_PLUGIN_MAP', " . var_export($map, true) . ");\n"
          . "}\n";
    
    $result->file(new FileMod($target, $code, FILE_RW, 0, false, true));
    // make sure we clear the error counters for at least number of plugins +1!
    // we don't know which error counters were remapped, so clear them all
    for($i=0, $m=count($plugins) +1; $i < $m; $i++) {
        $id = 768 + $i;
        $result->update(new CacheItem("STATS_{$id}", ƒ_id(0), ƒ_id(0), CACHE_HIGH));
    }

    return $result;
}



/**
 * The code that runs during plugin activation.
 * enable the firewall enable option, and install always on protection
 * on second activation (this is by design and based on "configured" flag)
 * TODO: move this code to -admin
 */
function activate_bitfire() {
    trace("wp_act");

    // make sure the config loader has run
    $config = parse_ini();
    // monitor any errors
    ob_start(function($x) { if(!empty($x)) {
        debug("PHP Warnings: [%s]\n", $x); }
        return $x;
    });

    include_once \plugin_dir_path(__FILE__) . "bitfire-admin.php";
    include_once \plugin_dir_path(__FILE__) . "src/server.php";

    $file_name = ini_get("auto_prepend_file");
    if (contains($file_name, "bitfire")) {
        $base_dir = realpath(dirname($file_name));
        CacheStorage::get_instance()->save_data("parse_ini", null, -86400);
        \BitFireSvr\uninstall()->run();
        sleep(1);
        \BitFireSvr\update_ini_value("rm_bitfire", $base_dir)->hide_output()->run();
    } else {
        \BitFireSvr\update_ini_value("rm_bitfire", "")->hide_output()->run();
    }


    // activate BitFire
    \BitfireSvr\bf_activation_effect()->hide_output()->run();

    // run the upgrade function if we have one
    if (function_exists("BitFireSvr\upgrade")) {
        \BitFireSvr\upgrade();
    }
    // TODO: move config data here ...
    if (defined('WP_CONTENT_DIR') && file_exists('WP_CONTENT_DIR')) {
        mkdir(WP_CONTENT_DIR . "/bitfire", 0775, false);
    }

    // install data can be verbose, so redirect to install log
    CFG::set_value("debug_file", false); 
    CFG::set_value("debug_header", false);
    ob_end_clean();


    debug(trace());
}




/**
 * The code that runs during plugin deactivation.
 * toggle the firewall enable option, uninstall
 * TODO: move this code to -admin
 */
function deactivate_bitfire() {
    trace("deactivate");

    // deactivate any cron jobs
    $ts = wp_next_scheduled('bitfire_scan_action');
    if ($ts) {
        // make sure we unschedule all events
        @wp_unschedule_event($ts, 'bitfire_scan_action');
        @wp_clear_scheduled_hook('bitfire_scan_action');
    }

    // install data can be verbose, so redirect to install log
    CFG::set_value("debug_file", true);
    CFG::set_value("debug_header", false);
    include_once \plugin_dir_path(__FILE__) . "bitfire-admin.php";
    \BitFireSvr\bf_deactivation_effect()->hide_output()->run();
    debug(trace());
}


function bitfire_admin_init() {

    /** don't show the bitfire menus if the user is not an admin, don't do any admin stuff if not on an admin page.. */
    if (!is_admin()) {
        return;
    }

    // since this is an admin page, make sure we have the admin functions loaded
    require_once \BitFire\WAF_SRC."dashboard.php";
    require_once \BitFire\WAF_SRC."server.php";
    require_once \BitFire\WAF_SRC."api.php";

    if (CFG::enabled("configured") == false) {
        $effect = update_config(get_hidden_file("config.json"));
        $effect->run();
    }

    // make sure we have a plugin map
    $result = update_plugin_list();
    $result->run();

    /* when any plugin is activated */
    add_action('activated_plugin', '\BitFirePlugin\update_plugin_list', 10, 2);

    /* when any plugin is deleted via the admin, i.e. uninstalled */
    add_action('deleted_plugin', '\BitFirePlugin\update_plugin_list', 10, 3);

    // add the menu, 
    add_action("admin_menu", "\BitFirePlugin\bitfire_add_menu");
    add_action("admin_notices", "\BitFirePlugin\alerts");

    //add_action("deactivated_plugin", "BitFirePlugin\bitfire_plugin_check");

    \register_activation_hook(__FILE__, 'BitFirePlugin\activate_bitfire');
    \register_deactivation_hook(__FILE__, 'BitFirePlugin\deactivate_bitfire');


    //add_filter("manage_users_columns", "BitFirePlugin\user_columns");
    //add_filter('manage_users_custom_column', "BitFirePlugin\custom_columns", 10, 3);


    // run the bitfire admin page code if we are showing the bitfire admin page
    if (isset($_GET["page"])) {
        $parts = explode("_", $_GET["page"]??'x');
        if ($parts[0] === "bitfire") {
            add_action("admin_enqueue_scripts", "\BitFirePlugin\bitfire_styles");
        }
    }
}

// make sure this is called!
function bitfire_uninstall() {
    include WAF_ROOT . "uninstall.php";
}

\add_action("wp_loaded", "BitFirePlugin\bitfire_admin_init");

register_uninstall_hook(__FILE__, 'BitFirePlugin\bitfire_uninstall');