<?php

namespace App\Console\Commands\Network;

use App\Console\Commands\BaseCommand;
use App\Helpers\Utility\UtilPrefix;
use Log;

class GroupFastBgp extends BaseCommand
{

    protected $signature = 'group:fast-bgp';

    protected $description = 'Sorts prefixes based on supernetting and subnetting.';

    public function handle()
    {
        $start = microtime(true);

        // We will always begin with attempting to fetch a fresh new route cache. We also want to know whether the files have changed so we track their timestamps.
        $detailed_time = filemtime(storage_path('prefix.detailed.json'));
        $detailed6_time = filemtime(storage_path('prefix.detailed6.json'));

        \Artisan::call('prefix:list-import');

        // Reserve this since we do a lot of "threading"
        $base = base_path();

        // Track whether list files were edited in the past minute...
        $edited_detailed = filemtime(storage_path('prefix.detailed.json')) != $detailed_time;
        $edited_detailed6 = filemtime(storage_path('prefix.detailed6.json')) != $detailed6_time;

        // We can guard against further automation if the configuration is broken by simply calling the configuration.
        UtilPrefix::get_detailed();
        UtilPrefix::get_detailed_v6();

        // These may be time based as they purely create things from the imported list...
        if($edited_detailed || $edited_detailed6) {
            $pipe = [
                0 => popen("php $base/artisan prefix:import", 'w'),
                1 => popen("php $base/artisan asn:import", 'w')
            ];
                
            pclose($pipe[0]);
            pclose($pipe[1]);

        }

        // These two quickly swap prefixes across ASNs and associate new prefixes with ASNs. Not candidates for phasing out on time as they handle organisation <-> organisation prefix shifts.
        \Artisan::call('prefix:associate');
        \Artisan::call('asn:reconcile');

        if($edited_detailed || $edited_detailed6) {

            // The following two tasks can execute simultaneously...
            $pipe = [
                0 => popen("php $base/artisan prefix:announce-v2", 'w'),
                1 => popen("php $base/artisan prefix:communities-v2", 'w')
            ];
                
            pclose($pipe[0]);
            pclose($pipe[1]);
        }
        elseif( (time() - filemtime(storage_path('prefix.detailed.json'))) > 300 || (time() - filemtime(storage_path('prefix.detailed6.json'))) > 300 ) { // Hack for now where we mark things as "Seen At" appropriately - Run it every five minutes.
            \Artisan::call('prefix:announce-v2');
        }

        // This must wait for everything else as communities are required to setup Mercury correctly...
        $pipe = [
            0 => popen("php $base/artisan goliath:setup", 'w'),
            1 => popen("php $base/artisan geoip:setup", 'w'),
            2 => popen("php $base/artisan prefix:reassociate", 'w'),
            3 => popen("php $base/artisan goliath:location-sync", 'w')
        ];

        pclose($pipe[0]);
        pclose($pipe[1]);
        pclose($pipe[2]);
        pclose($pipe[3]);

        \Artisan::call('prefix:delete');

        if(($time_taken = microtime(true) - $start) && $time_taken > 15) {
            \Log::debug("Fast BGP execution has exceeded safe time: " . (microtime(true) - $start));
        }
    
        return 0;
    }
}