<?php
namespace Watcher;

class Watcher
{
    ///Logger instance
    public  $Log;

    ///State vriables
    private $initialized=false;
    private $running=false;
    private $stopped=true;

    ///
    ///DB columns
    ///
    public static $tableName="watcher";
    public static $colLastUpdate="last_update";
    public static $colLastPID="last_pid"; 
    public static $colMutext="";
    public static $colID ="id";
    public static $onlyID=1;
    public static $colPaused="paused";

    ///
    /// Instance variables
    ///
    private $lastUpdate;
    private $lastPID;
    private $paused;

    public $clients;

    private $torrentDistributionList;



public function Initialize()
    {
        $this->Log= new \Shared\Logger(\Shared\Settings::$WatcherServiceLogFile,true);
        $this->Log->ClearLog();
        $this->torrentDistributionList=array();


        $this->initialized=true;
        $GLOBALS['currentWatcher'] = $this;
        $this->Log->LogString("Watcher initialized.");
    }

    public function StartWatcher()
    {
        if(!$this->initialized) throw new Exception("Watcher must be initialized first.");
        if($this->running) throw new Exception("Watcher already running");
        $this->stopped=false;
        $this->running=true;

        $data=self::GetWatcher();
        
        $this->Actualize();
        $this->lastUpdate = new \DateTime();
        $this->UpdateOrSave();

        $this->Log->LogString("============Watcher started.============");
        $this->Log->LogString("Current watcher running on: ".\Shared\PInfo::CurrentOS()." PID: ".getmypid(). (\Shared\PInfo::IsPIDActive(getmypid())?" active":"inactive") );
        $wasPaused=false;
        while (!$this->stopped)
        {
            
            $this->Log->LogString("======Watcher cycle started.======");
            
            //smyčka pauzy služby
            do
            {
                $this->Actualize();
                if($this->paused) {
                    $wasPaused=true;
                    $this->Log->LogString("Watcher is paused.");
                    sleep(2);
                }
            }
            while($this->paused);

            if($wasPaused)$this->Log->LogString("Watcher is resumed.");
            
            $this->LoadDistributionList();
            
            $this->clients = DBuTorrentClient::GetClients($this);
            $this->Log->LogString("Clients loaded with ". count($this->clients)." items.");

            foreach($this->clients as $client )
                { 
                $client->Log=$this->Log;    
                $client->Actualize();
                }

            
            foreach($this->clients as $client )
            { 
                if(!$client->Active)
                    continue;    
                $client->UpdateOrSave();  
            }

            //agregování zjištěných hodnot stavu distribučníholistu
            $this->updateDistributionListStates();    
            
            //opětovné načtení z DB -stav paused se v průběhu algoritmu mohl změnit konkurenčním přístupem admina
            $this->Actualize();
            
            // uloĹľenĂ­ aktualizovanĂ©ho stavu
            $this->lastUpdate = new \DateTime();
            $this->UpdateOrSave();

            $commander = new \Commander\Commander($this);
            $commander->CommandingCycle();


            sleep(\Shared\Settings::$UpdateIntervalInSecodns);

            \Shared\Debug::Instance()->Activate()->Display("Watcher cycle end",$this)->Deactivate();
            gc_collect_cycles();
            
        $this->Log->LogString("======Watcher cycle completed, updated: ". count($this->clients)." clients with ".$this->getTorrentsCount()." torrents.======\r\n");
        }
        $this->Log->LogString("Watcher stopped.");
    }

    private function updateDistributionListStates()
    {
         // ULOZENI AKTUALIZOVANEHO SEZNAMU DISTRIBUCNIHO LISTU
         foreach($this->torrentDistributionList as $distribution)
         {
                 // LOGOVANI DISTRIBUCE
             if(!$distribution->AllInstalled)
                 $this->Log->LogString("Distribution ". $distribution->Name . " is not properly installed everywhere");     
             if($distribution->SomeExtra)
                 $this->Log->LogString("Disabled distribution ". $distribution->Name . " is somewhere still installed");  
             if($distribution->SomePaused)
                 $this->Log->LogString("Distribution ". $distribution->Name . " is somewhere paused");
 
             $distribution->SaveProgressData();
         }
    }
    

    public function Stop()
    {
        $this->stopped=true;
        $this->running=false;
    }

    public function Actualize()
    {
        $data=self::GetWatcher();
        $this->lastUpdate=new \DateTime($data[self::$colLastUpdate]);
        $this->lastPID=getmypid();
        $this->paused=$data[self::$colPaused]==1;
    }

    private function UpdateOrSave()
    {   
        self::UpdateWatcherData(array(  self::$colLastPID => $this->lastPID,
                    self::$colLastUpdate => $this->lastUpdate->format('Y-m-d H:i:s'),
                    self::$colPaused=>$this->paused?1:0)
                );
    }

    public static function UpdateWatcherData($data)
    {
        $sql=\Shared\MySQL::GetMySQL()->where(self::$colID, self::$onlyID)->update(self::$tableName,$data);
    }

    private function getTorrentsCount()
    {
        $count=0;
        foreach($this->clients as $cl)
        {
            $count +=count($cl->GetTorrents());
        }
        return $count;
    }

    public static function GetCurrentWatcher()
    {
        return $GLOBALS['currentWatcher'];
    }

    public function GetTorrentDistributionList()
    {
        return $this->torrentDistributionList;
    }

    private function loadDistributionList()
    {
        $this->torrentDistributionList= \Shared\DBTorrentToDistribute::GetTorrentsDistributionList();
        foreach($this->torrentDistributionList as $distribution)
        {
            $distribution->AllInstalled=true;
            $distribution->SomeExtra=false;
            $distribution->SomePaused=false;
        }
        $this->Log->LogString("Distribution list loaded with ". count($this->torrentDistributionList)." items.");
    }

    public static function GetWatcher()
    {
        $arr=\Shared\MySQL::GetMySQL()->where(self::$colID,self::$onlyID)->get(self::$tableName,
        array(self::$colLastUpdate, self::$colLastPID,self::$colPaused));
        return $arr[0];
    }

}
