#!/usr/bin/env php
<?php

namespace Aowow;

require_once 'includes/kernel.php';
require_once 'includes/setup/cli.class.php';

/* todo (med):
    * tidy this file
    * make win-safe
*/

if (!CLI)
    die("this script must be run from CLI\n");
if (CLI && getcwd().DIRECTORY_SEPARATOR.'prQueue' != __FILE__)
    die("this script must be run from root directory\n");

if ($_ = getopt('', ['log::']))
    if (!empty($_['log']))
        CLI::initLogFile(trim($_['log']));

// check if we already have a queue running
if (!Profiler::queueLock(getmypid()))
    exit();


CLI::write('profiler queue started', CLI::LOG_OK);
set_time_limit(0);
$tCycle = microtime(true);

$error = function (int $type, int $realmGUID, int $realmId, int $fetchResult) : void
{
    $what = match ($type)
    {
        Type::PROFILE    => 'char',
        Type::GUILD      => 'guild',
        Type::ARENA_TEAM => 'arena team'
    };

    $msg = match ($fetchResult)
    {
        Profiler::FETCH_RESULT_ERR_NAME_EMPTY  => 'Subject has an empty name and was skipped.',
        Profiler::FETCH_RESULT_ERR_NOT_FOUND   => 'Subject was not found. Truncating local placeholder.',
        Profiler::FETCH_RESULT_ERR_NO_MEMBERS  => 'Subject has no members. Truncating local placeholder.',
        Profiler::FETCH_RESULT_ERR_INTERNAL    => 'Internal Error - Data stub is missing.'
    };

    trigger_error('prQueue - [realm: '.$realmId.' '.$what.' guid: '.$realmGUID.'] '.$msg, E_USER_WARNING);

    DB::Aowow()->qry('UPDATE ::profiler_sync SET `status` = %i, `errorCode` = %i WHERE `realm` = %i AND `realmGUID` = %i AND `type` = %i', PR_QUEUE_STATUS_ERROR, PR_QUEUE_ERROR_CHAR, $realmId, $realmGUID, $type);
};


while (Cfg::get('PROFILER_ENABLE', true))
{
    $delay = Cfg::get('PROFILER_QUEUE_DELAY') / 1000;
    if (($tDiff = (microtime(true) - $tCycle)) < $delay)
    {
        $wait = $delay - $tDiff;
        CLI::write('sleeping '.Lang::nf($wait, 2).'s..');
        usleep($wait * 1000 * 1000);
    }

    $row = DB::Aowow()->selectRow('SELECT * FROM ::profiler_sync WHERE `status` = %i ORDER BY `requestTime` ASC', PR_QUEUE_STATUS_WAITING);
    if (!$row)
    {
        // nothing more to do
        CLI::write('profiler queue empty - process halted!', CLI::LOG_INFO);
        Profiler::queueFree();
        exit();
    }
    // scheduled for future date
    if ($row['requestTime'] > time())
        continue;

    if (empty(Profiler::getRealms()[$row['realm']]))
    {
        DB::Aowow()->qry('UPDATE ::profiler_sync SET `status` = %i, `errorCode` = %i WHERE `realm` = %i AND `type` = %i AND `typeId` = %i', PR_QUEUE_STATUS_ERROR, PR_QUEUE_ERROR_ARMORY, $row['realm'], $row['type'], $row['typeId']);
        CLI::write('realm #'.$row['realm'].' for subject guid '.$row['realmGUID'].' is missing/inaccessible.', CLI::LOG_WARN);
        continue;
    }
    else
        DB::Aowow()->qry('UPDATE ::profiler_sync SET `status` = %i WHERE `realm` = %i AND `type` = %i AND `typeId` = %i', PR_QUEUE_STATUS_WORKING, $row['realm'], $row['type'], $row['typeId']);

    switch ($row['type'])
    {
        case Type::PROFILE:
            switch ($result = Profiler::getCharFromRealm($row['realm'], $row['realmGUID']))
            {
                case Profiler::FETCH_RESULT_OK_UNCHANGED:
                    CLI::write('char #'.$row['realmGUID'].' on realm #'.$row['realm'].' did not log in since last update. skipping...');
                case Profiler::FETCH_RESULT_OK:
                    break 2;
                case Profiler::FETCH_RESULT_ERR_NAME_EMPTY:
                case Profiler::FETCH_RESULT_ERR_NOT_FOUND:
                    DB::Aowow()->qry('DELETE FROM ::profiler_profiles WHERE `realm` = %i AND `realmGUID` = %i', $row['realm'], $row['realmGUID']);
                default:
                    $error(Type::PROFILE, $row['realmGUID'], $row['realm'], $result);
                    continue 3;
            }
        case Type::GUILD:
            switch ($result = Profiler::getGuildFromRealm($row['realm'], $row['realmGUID']))
            {
                case Profiler::FETCH_RESULT_OK:
                    break 2;
                case Profiler::FETCH_RESULT_ERR_NAME_EMPTY:
                case Profiler::FETCH_RESULT_ERR_NOT_FOUND:
                case Profiler::FETCH_RESULT_ERR_NO_MEMBERS:
                    DB::Aowow()->qry('DELETE FROM ::profiler_guild WHERE `realm` = %i AND `realmGUID` = %i', $row['realm'], $row['realmGUID']);
                default:
                    $error(Type::GUILD, $row['realmGUID'], $row['realm'], $result);
                    continue 3;
            }
        case Type::ARENA_TEAM:
            switch ($result = Profiler::getArenaTeamFromRealm($row['realm'], $row['realmGUID']))
            {
                case Profiler::FETCH_RESULT_OK:
                    break 2;
                case Profiler::FETCH_RESULT_ERR_NAME_EMPTY:
                case Profiler::FETCH_RESULT_ERR_NOT_FOUND:
                case Profiler::FETCH_RESULT_ERR_NO_MEMBERS:
                    DB::Aowow()->qry('DELETE FROM ::profiler_arena_team WHERE `realm` = %i AND `realmGUID` = %i', $row['realm'], $row['realmGUID']);
                default:
                    $error(Type::ARENA_TEAM, $row['realmGUID'], $row['realm'], $result);
                    continue 3;
            }
        default:
            DB::Aowow()->qry('DELETE FROM ::profiler_sync WHERE realm = %i AND type = %i AND typeId = %i', $row['realm'], $row['type'], $row['typeId']);
            trigger_error('prQueue - unknown type #'.$row['type'].' to sync into profiler. Removing from queue...', E_USER_ERROR);
    }

    $tCycle = microtime(true);

    // mark as ready
    DB::Aowow()->qry('UPDATE ::profiler_sync SET `status` = %i, `errorCode` = 0 WHERE `realm` = %i AND `type` = %i AND `typeId` = %i', PR_QUEUE_STATUS_READY, $row['realm'], $row['type'], $row['typeId']);
}

Profiler::queueFree();
CLI::write('profiler queue halted!', CLI::LOG_INFO);

?>
