<?php
/**
 * Copyright (c) 2018.
 * Author: Igor Barkov <lopar.4ever@gmail.com>
 * Project name: Battles-Game
 */

use Battles\Chat;
use Battles\Database\Db;
use Battles\Travel;
use Battles\User;
use Battles\UserStats;

require_once 'config.php';

if (empty($_SESSION['uid'])) {
    header("Location: index.php");
    exit;
}

if (User::getInstance()->getBlock()) {
    exit('user blocked!');
}

//Проверки на соответствие скрипта и комнаты, которые были натыканы по всем файлам.
Travel::roomRedirects(User::getInstance()->getRoom(), User::getInstance()->getBattle());

if (
    !empty($_GET['goto']) &&
    !empty($_GET['tStamp']) &&
    !empty($_GET['vcode']) &&
    $_GET['vcode'] == md5(sha1($_GET['goto'] . $_GET['tStamp']))
) {
    $query = 'update users u, online o set u.room = ?, o.room = ? where user_id = id and user_id = ?';
    Db::getInstance()->execute($query, [$_GET['goto'], $_GET['goto'], User::getInstance()->getId()]);
    User::getInstance()->setRoom(intval($_GET['goto']));
}

function createbot($bot, $login = null): array
{
    if (empty($login)) {
        $login = Db::getInstance()->fetchColumn('select login from users where id = ?', $bot);
    }
    if (empty($login)) {
        return [];
    }
    Db::getInstance()->execute('insert into bots (name, prototype) values (?,?)', [$login, $bot]);
    return [
        'id' => Db::getInstance()->lastInsertId(),
        'login' => $login,
    ];
}

$var_map = [
    'cell_1' => 'Березовая роща', 'cell_2' => 'Березовая просека', 'cell_3' => 'Тёмный угол', 'cell_4' => 'Мрачная опушка',
    'cell_5' => 'Тёмное урочище', 'cell_6' => 'Бурелом', 'cell_7' => 'Старая ива', 'cell_8' => 'Разнолесье',
    'cell_9' => 'Сосновая тропа', 'cell_10' => 'Забытая дорога', 'cell_11' => 'Новая дорога', 'cell_12' => 'Мщаник',
    'cell_13' => 'Ясная поляна', 'cell_14' => 'Заросший тракт', 'cell_15' => 'Смутный ельник', 'cell_16' => 'Сосновый бор',
    'cell_17' => 'Тихоход', 'cell_18' => 'Сосновый гай', 'cell_19' => 'Смешаный лес', 'cell_20' => 'Темная поляна',
    'cell_21' => 'Осенний угол', 'cell_22' => 'Грибное место', 'cell_23' => 'Опушка', 'cell_24' => 'Рыжий лес',
    'cell_25' => 'Полесье',
];

const _BOTSEPARATOR_ = 10000000;

function savecavedata($cavedata, $caveleader, $floor)
{
    $f1 = fopen("cavedata/$caveleader-$floor.dat", "wb+");
    flock($f1, LOCK_EX);
    fwrite($f1, serialize($cavedata));
    flock($f1, LOCK_UN);
    fclose($f1);
}

/**
 * Генератор прогрессбара.
 *
 * @param        $current    - Текущее значение.
 * @param        $maximum    - Максимальное значение.
 * @param string $lineColor - Цвет полоски прогрессбара.
 * @param string $bgColor   - Фон прогрессбара.
 *
 * @return string
 */
function showProgressBar($current, $maximum, string $lineColor = 'limegreen', string $bgColor = 'silver'): string
{
    $bar = round($current / $maximum * 100);
    return <<<HTML
    <div style="width: 100%; height: 16px; background: $bgColor; overflow: hidden; border-radius: 3px;">
        <div style="height: 16px; background: $lineColor; border-radius: 3px; width: $bar%;"></div>
    </div>
    <div style="width: 100%; height: 16px; font-size: 14px; text-align: center; margi
    n-top: -16px;">
        $current / $maximum
    </div>
HTML;
}


/**
 * Функция отображает слот для свитков в окне персонажа.
 *
 * @param $slot
 *
 * @return string
 */
function echoscroll($slot): string
{
    $allMagic = 0;
    if (User::getInstance()->getBattle()) {
        $script = 'fbattle';
        $allMagic = Db::getInstance()->fetchColumn('select magic from battle where id = ?', User::getInstance()->getBattle());
        $allMagic = unserialize($allMagic);
    } else {
        $script = 'main';
    }
    $dress = Db::getInstance()->fetch('select magic, name, image, durability from inventory where item_id = ?', User::getInstance()->$slot);
    $needCharge = Db::getInstance()->fetchColumn('select needcharge from magic where id = ?', $dress['magic']);
    $str = null;
    if ((User::getInstance()->$slot > 0) && ($allMagic[User::getInstance()->getId()] < 1 || empty($needCharge))) {
        $row['id'] = User::getInstance()->$slot;
        if ($dress['magic']) {
            $magicTargeted = Db::getInstance()->fetchColumn('select targeted from magic where id = ?', $dress['magic']);
            $str .= "<a onclick=\"";
            if ($magicTargeted === 1) {
                $str .= "okno('Введите название предмета', '" . $script . ".php?use={$row['id']}', 'target'); ";
            } elseif ($magicTargeted === 2) {
                    $str .= "findlogin('Введите имя персонажа', '" . $script . ".php?use={$row['id']}', 'target'); ";
                } else {
                    $str .= "if(confirm('Использовать сейчас?')) { window.location='" . $script . ".php?use=" . $row['id'] . "';}";
                }
            $str .= "\"href='#'>";
        }
        $str .= <<<ACTIVE_SCROLL
<img class='tooltip' src="i/sh/{$dress['img']}" width='40' title="<b>{$dress['name']}</b><br> Прочность {$dress['duration']} / {$dress['maxdur']} " height='25' alt="Свиток"></a>
ACTIVE_SCROLL;
    } elseif ((User::getInstance()->$slot > 0) && ($allMagic[User::getInstance()->getId()] >= 1) && $needCharge['needcharge'] > 0) {
        $str .= <<<INACTIVE_SCROLL
<img src="i/sh/magicclock.gif" width="40" height="25" title='Произведите размен ударами и магия снова станет доступна' alt="Свиток">
INACTIVE_SCROLL;
    } else {
        $str .= <<<EMPTY_SLOT
<img class="tooltip" src="i/w13.gif" width="40" height="25" title='<b>Пустой слот магия</b>' alt="Слот для свитка">
EMPTY_SLOT;
    }
    return $str;
}

function timeOut($ttm): string
{
    require_once 'classes/quests_class.php';
    $q = new Quests();
    return $q->timeOut($ttm);
}

/**
 * @param $time
 * @param $vars
 * @param $vls
 * @param $uid
 */
function addActions($time, $vars, $vls, $uid)
{
    $query = 'insert into actions (uid, time, city, room, vars, ip, vals) values (?,?,?,?,?,?,?)';
    $values = [$uid, $time, 'capitalcity', 0, $vars, $_SERVER['REMOTE_ADDR'], $vls];
    Db::getInstance()->execute('lock tables actions write');
    Db::getInstance()->execute($query, $values);
    Db::getInstance()->execute('unlock tables');
}

/* ВАЖНО! (#44)
 * addch() и addchp() заменяются на Chat::class->sendSys($message, [optional]$receiver);
 * Для addchp() используется второй опциональный ключ.
 * Это 150+ вхождений в куче файлов, где надо менять структуру вызова функции из-за их несовместимости.
 * Возможно, приоритетом стоит сделать унификацию свитков нападения, которых самих около 20 и которые
 * по нескольку раз вызывают эти функции.
 */

/**
 * @param $text
 * @param $room
 * @param $smth
 * @return void
 * @deprecated use Chat::sendSys($msg) instead.
 */
function addch($text, $room = 0, $smth = null)
{
    Chat::sendSys($text);
}


/**
 * @param $text
 * @param $who
 * @param $room
 * @return void
 * @deprecated use Chat::sendSys($msg, $receiverId) instead.
 */
function addchp($text, $who, $room = 0)
{
    Chat::sendSys($text, $who);
}

function err($t)
{
    echo '<span class="error">' . $t . '</span>';
}


/**
 * @param int    $userId
 * @param string $text
 *
 */
function telegraph(int $userId, string $text)
{
    if (User::getInstance($userId)->getId() > 0) {
        Chat::sendTelegraf($text, $userId);
    }
}

function SolveExp($at_id, $def_id, $damage): float
{
    $mods = [
        'bloodb' => 1.2,
        'btl_1' => 1,
        'btl_2' => 0.5,
        'btl_3' => 0.05,
    ];
    $baseexp = [
        "0" => "2",
        "1" => "5",
        "2" => "10",
        "3" => "15",
        "4" => "30",
        "5" => "60",
        "6" => "90",
        "7" => "115",
        "8" => "300",
        "9" => "400",
        "10" => "500",
        "11" => "600",
        "12" => "700",
        "13" => "800",
        "14" => "900",
        "15" => "1000",
        "16" => "1100",
        "17" => "1200",
        "18" => "1300",
        "19" => "1400",
        "20" => "1500",
        "21" => "1600",
    ];
    $expmf = 0;
    $bot_active = false;
    $bot_def = false;

    if ($at_id > _BOTSEPARATOR_) {
        $at_id = Db::getInstance()->fetchColumn('select prototype from bots where bot_id = ?', $at_id);
        $bot_active = true;
    }

    $query = 'select greatest(1, sum(price)) as allprice from users left join inventory on users.id = inventory.owner_id where id = ?';
    $atAllPrice = Db::getInstance()->fetchColumn($query, $at_id);
    $defAllPrice = Db::getInstance()->fetchColumn($query, $def_id);

    $atInfo = new UserStats($at_id);
    $defInfo = new UserStats($def_id);

    $table_name = $at_id > _BOTSEPARATOR_ ? 'bots' : 'users';
    $bt = Db::getInstance()->ofetch('select blood, type, t1, t2 from battle where battle_id = (select battle from ? where id = ?)', [$table_name, $at_id]);

    if ($def_id > _BOTSEPARATOR_) {
        $def_id = Db::getInstance()->fetchColumn('select prototype from bots where bot_id = ?', $def_id);
        $bot_def = true;
    }

    if ($bt->blood) {
        $expmf = $mods['bloodb'];
    }

    $filebtl = '/tmp/' . $at_id . '.btl';
    if ($bt->type == 1 && file_exists($filebtl)) {
        $btfl = fopen($filebtl, 'r');
        $contents = fread($btfl, filesize($filebtl));
        fclose($btfl);
        $cnt = substr_count($contents, $def_id);
        $exmod = 1;

        if ($cnt <= 1) {
            $exmod = $mods['btl_1'];
        } elseif ($cnt == 2) {
            $exmod = $mods['btl_2'];
        } elseif ($cnt > 2) {
            $exmod = $mods['btl_3'];
        }
        $expmf = $expmf * $exmod;
    }

    $standart = [
        "0" => 1,
        "1" => 1,
        "2" => 15,
        "3" => 111,
        "4" => 265,
        "5" => 526,
        "6" => 882,
        "7" => 919,
        "8" => 919,
        "9" => 919,
        "10" => 919,
        "11" => 919,
        "12" => 919,
        "13" => 919,
        "14" => 919,
        "15" => 919,
        "16" => 919,
        "17" => 919,
        "18" => 919,
        "19" => 919,
        "20" => 919,
        "21" => 919,
        "22" => 919,
        "23" => 919,
        "24" => 919,
        "25" => 919
    ];

    $mfit = ($atAllPrice / ($standart[$atInfo->getLevel()] / 3));
    if ($mfit < 0.8) {
        $mfit = 0.8;
    }
    if ($mfit > 1.5) {
        $mfit = 1.5;
    }

    $pls = count(explode(";", $bt->t1)) + count(explode(";", $bt->t2));
    if ($pls > 2) {
        $mfbot = $bot_active ? 0.3 : 1;
        $mfbot2 = $bot_def ? 0.7 : 1;
    } else {
        $mfbot = 1;
        $mfbot2 = 1;
    }
    if ($expmf == 0) {
        $expmf = 1;
    }

    return round((($baseexp[$defInfo->getLevel()]) * ($defAllPrice / (($atAllPrice + $defAllPrice) / 2)) * ($damage / $defInfo->getMaxHealth()) * $expmf * $mfit * $mfbot * $mfbot2) / 3);
}