<?php
namespace Watcher;

class DBuTorrentClient extends \Commander\UTorrentClient
{

    public static $tableName = "client";
    public static $colLastUpdate = "last_update";
    public static $colID = "ID";
    public static $colAddress = "address";
    public static $colPort= "port";
    public static $colTitle = "title";
    public static $colConnected="connected";
    public static $colActive ="active";

    private $id=null;
    public $title;
    public $Active;

    public $Log;
    public $MissingTorrents=array();
    public $ExtraTorrents=array();

    #region static

    public static function GetClients()
    {
        $clients=array();
        $clientsRows=self::GetClientsData();
        foreach ($clientsRows as $clientRow)
        {
            $cl= new DBuTorrentClient($clientRow);
            $cl->Groups=$cl->GetGroups();
            $clients[$clientRow[self::$colID]]=$cl;
 //           var_dump($cl);
        }
        
        return $clients;
    }

    private function GetGroups()
    {
        $this->Groups=self::getClientGroups($this->id);
       return $this->Groups;
    }

    public function AddGroupByName($nameToAdd)
    {
        if(trim($nameToAdd)=="")return;
        $result=\Shared\MySQL::GetMySQL()->where("groupname",$nameToAdd)->get("groups",array("id"));
        if(!$result)// groupa neexistuje - založení nové
        {
            $sql=\Shared\MySQL::GetMySQL()->insert("groups", array("groupname"=>$nameToAdd));
            $result=\Shared\MySQL::GetMySQL()->where("groupname",$nameToAdd)->get("groups",array("id"));
            \Shared\Messages::Information("Group ".$nameToAdd." created.");
        }

        $sql=\Shared\MySQL::GetMySQL()->insert("clientgroup", array(  
            "idgroup" => $result[0]["id"],
            "idclient" => $this->id)
            ); 
        return $sql;    
    }
    public function RemoveGroup($nameToAdd)
    {
        $result=\Shared\MySQL::GetMySQL()->where("groupname",$nameToAdd)->get("groups",array("id"));
        $sql=\Shared\MySQL::GetMySQL()->where(array("idgroup"=>$result[0]["id"], "idclient"=>$this->id))->delete("clientgroup"); 
        return $sql;    
    }

    public static function GetClientsData()
    {
        $rows=\Shared\MySQL::GetMySQL()->get(self::$tableName,self::getArrayForSelect());
        $new=array(); 
        if(!is_array($rows)) return $new;
        foreach($rows as $clientRow)
        {
            $dt= new \DateTime($clientRow[self::$colLastUpdate]);
            $clientRow[self::$colLastUpdate]=$dt->format("j.n.Y h:i:s");
            $clientRow[self::$colConnected]=$clientRow[self::$colConnected]==1;
            $clientRow[self::$colActive]=$clientRow[self::$colActive]==1;
            $clientRow["groups"]=self::getClientGroups($clientRow[self::$colID]);
            array_push($new,$clientRow);
        }
        return $new;
    }
    private static function getClientGroups($idClient)
    {
        $rows=\Shared\MySQL::GetMySQL()->query("SELECT g.id,g.groupname from %db%.clientgroup cg inner join %db%.groups g on g.id=cg.idgroup where cg.idclient=?",array("i" => $idClient));
        $groups=array();
        foreach($rows as $row)
        {
            array_push($groups, $row["groupname"]);
        }
        return $groups;
    }

    private static function getArrayForSelect()
    {
        return array(
            self::$colID,
            self::$colLastUpdate,
            self::$colAddress,
            self::$colPort,
            self::$colTitle,
            self::$colConnected,
            self::$colActive
        );
    }

    public static function GetById($id)
    {   
        $row=\Shared\MySQL::GetMySQL()->where(self::$colID,$id)->get(self::$tableName, self::getArrayForSelect());
        $cl=new DBuTorrentClient($row[0]);
        $cl->GetGroups();
        return $cl;

    }
    #endregion static

    public function __construct($row){
        parent::__construct($row[self::$colAddress],$row[self::$colPort]);
        $this->id=@$row[self::$colID];
        $this->lastUpdate=@$row[self::$colLastUpdate];
        $this->title=$row[self::$colTitle];
        $this->Connected=@$row[self::$colConnected];
        $this->Active=@$row[self::$colActive];
        $this->Groups=$this->GetGroups();
       }

    public function Actualize()
    {   
        if(!$this->Active)
            {
                $this->Log->LogString("Skipping deactivated client ".$this->title." (".$this->IPAddress.":".$this->Port.")");   
                return;  
            }
        
        $this->Log->LogString("Updating client ".$this->title." (".$this->IPAddress.":".$this->Port.")");     

        parent::Actualize();//zde se nacĂ­tajĂ­ data z k API      
        if($this->Connected)
            $this->Log->LogString("Client ".$this->IPAddress.":".$this->Port. " succesfully connected.");                       
        else
            $this->Log->LogString("Client ".$this->IPAddress.":".$this->Port. " NOT reached.");

        $dbtorrs=DBTorrent::LoadTorrentsFromDatabase($this); //nacteni dat z DB z predchozí­ho cyklu
        \Shared\Debug::Instance()->Activate()->Display("Torrents from DB Loaded",$dbtorrs)->Deactivate();     

        ///ODEBRANI TORRENTU Z DB - TECH KTERE API UZ NEVRACI
        $this->removeLost($dbtorrs);

         ///NAPAROVANI TORRENTU Z API s TEMI V DB
        $this->pairAPIWithDBIDs($dbtorrs);
       
         /// KONTROLA INSTALACE všech distribucí na klientech
        $watcher=Watcher::GetCurrentWatcher();
        $distributionList= $watcher->GetTorrentDistributionList();
        $this->checkInstallations($distributionList);
 
        $this->UpdateOrSave();
    }

    private function checkInstallations($distributionList)
    {
        
        foreach($distributionList as $distribution)
            {
                if($distribution->Active && sizeof(array_intersect($distribution->Groups,$this->Groups))>0)
                {   //nalezeni chybejicich torrentu
                    
                    if(!isset($this->Torrents[$distribution->Name]))
                        {                    
                            $this->MissingTorrents[$distribution->Name]=$distribution;
                            $distribution->AllInstalled=false;

                            //LOGOVANI TORRENTU
                            $this->Log->LogString("Torrent ". $distribution->Name . " missing at ". $this->IPAddress.":".$this->Port);
                        }
                    else
                        {
                            $this->Torrents[$distribution->Name]->isForDistribution=true;
                        }

                        //vyhledani pausnutych/zastavenych torrentu
                        $rest =array_filter($this->Torrents, function($element) use($distribution)
                                                { 
                                                    //var_dump($element->Status);
                                                    return $element->Name==$distribution->Name &&
                                                         $element->isForDistribution && 
                                                        (DBTorrent::IsPaused($element->Status)||!DBTorrent::IsStarted($element->Status));
                                                });
                        if(count($rest)>0)
                        {
                            $distribution->SomePaused=true; 
                             //LOGOVANI TORRENTU
                             $this->Log->LogString("Torrent ". $distribution->Name . " is paused at ". $this->IPAddress.":".$this->Port);
                        }
                }
                else
                {   //nalezeni prebyvajicich torrentu
                    //(array_intersect($distribution->Groups,$this->Groups));
                    if(isset($this->Torrents[$distribution->Name])&& sizeof(array_intersect($distribution->Groups,$this->Groups))==0)
                    {         
                        $this->ExtraTorrents[$distribution->Name]=$this->Torrents[$distribution->Name];
                        $distribution->SomeExtra=true;
                        $this->Torrents[$distribution->Name]->isForDistribution=false;

                        //LOGOVANI TORRENTU
                        $this->Log->LogString("Torrent ". $distribution->Name . " is extra at ". $this->IPAddress.":".$this->Port);                       
                    }
                }
            }

        // nalezeni uplne neznamych torrentu
        foreach($this->Torrents as $torr)
        {
            if(!isset($distributionList[$torr->Name])){
                $this->ExtraTorrents[$torr->Name]=$torr;
                $this->Log->LogString("Torrent ". $torr->Name . " is extra at ". $this->IPAddress.":".$this->Port."(it is not in distribution list)");
            }
        }

        //LOGOVANI CLIENTA
        if(count($this->ExtraTorrents)>0)
            $this->Log->LogString("Client ". $this->IPAddress.":".$this->Port ." has some extra torrents.");      
        if(count($this->MissingTorrents)>0)
            $this->Log->LogString("Client ". $this->IPAddress.":".$this->Port . " doesnt have all torrents installed.");   
            
        
    }
    
    private function removeLost($dbtorrs)
    {
          // ODSTRANENI Z DB TECH PREBYTECNYCH
          foreach($dbtorrs as $dbtorr )
          {
                  if(!array_key_exists($dbtorr->Name,$this->Torrents)) // pokud uĹľ neexistuje - smaĹľeme ho
                  {
                      $dbtorr->Delete();
                  }
          }
    }

    private function pairAPIWithDBIDs($dbtorrs)
    {
        /// SPRAVANI NALEZENZCH na API s TEMI V DB
        foreach($this->Torrents as $torrent )
        {
            $nTorrent=new DBTorrent($this->Torrents[$torrent->Name],$this);
            
            if(array_key_exists($nTorrent->Name,$dbtorrs))
            {
                $nTorrent->SetID($dbtorrs[$nTorrent->Name]->GetID());
                \Shared\Debug::Instance()->Activate()->Display("Setting ID to reloaded torrent:",$nTorrent)->Deactivate();
            }
            
            $this->Torrents[$nTorrent->Name]=$nTorrent;        
        }
    }

    public function UpdateOrSave()
    {
        $this->lastUpdate = new \DateTime(); 
        if($this->id==null)
        {
            $sql=\Shared\MySQL::GetMySQL()->insert(self::$tableName, array(  
                self::$colLastUpdate => $this->lastUpdate->format('Y-m-d H:i:s'),
                self::$colAddress => trim($this->IPAddress),
                self::$colPort => trim($this->Port),
                self::$colTitle => $this->title,
                self::$colConnected =>$this->Connected?1:0,
                self::$colActive =>$this->Active?1:0
                    )
                );     
                $this->id=\Shared\MySQL::GetMySQL()->insert_id();
                return $sql;
        }
        
        $sql=\Shared\MySQL::GetMySQL()->where(self::$colID, $this->id)->update(self::$tableName, array(  
                self::$colLastUpdate => $this->lastUpdate->format('Y-m-d H:i:s'),
                self::$colAddress => $this->IPAddress,
                self::$colPort => $this->Port,
                self::$colTitle =>$this->title,
                self::$colConnected =>$this->Connected?1:0,
                self::$colActive =>$this->Active?1:0
                )
                    );     
                    
        //ULOZENI INFORMACI O TORRENTECH
        foreach($this->Torrents as $Torrent)
        {
            $Torrent->UpdateOrSave();
        }
        return $sql;
    }

    public static function Delete($id)
    {
        $client=self::GetById($id);
        $dbtorrs=DBTorrent::LoadTorrentsFromDatabase($client);
        foreach($dbtorrs as $torr)
        {
            $torr->Delete();
        }var_dump($client->Groups);
        foreach($client->Groups as $group)
        {
            $client->RemoveGroup($group);  
            \Shared\Messages::Information("Group ".$group." unassigned.");          
        }
        return $sql=\Shared\MySQL::GetMySQL()->where(self::$colID, $id)->delete(self::$tableName);     
    }

    public function GetID()
    {
        return $this->id;
    }

   
}