<?php

class Announcement {
    
    private $id;
    private $text;
    private $attachedFile;
    private $expiredDate;
    
    public function __construct($text, DateTime $expiredDate = null, AttachedFile $attachedFile = null, $id = null) {
        
        if (trim(strip_tags($text)) === '' && $attachedFile === null) {
            
            throw new Exception('Announcement can\'t have no text and no file');           
            
        }
        
        if ($expiredDate !== null && (int)$expiredDate->format('U') > pow(2, 31) - 1) {
            
            throw new Exception('Too big expired date');   
            
        }
        
        if ($id !== null && !ctype_digit((string)$id)) {
            
            throw new Exception('Announcement id must be numeric');
            
        }
        
        $this->id = $id;
        $this->text = trim($text);
        $this->attachedFile = $attachedFile;
        $this->expiredDate = $expiredDate;            
            
        
    }
    
    public function putToDatabase() {
        
        $mysqli = new mysqli(DATABASE_SERVER, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME);
        
        if (mysqli_connect_error()) {
            
            throw new Exception('Can\'t connect to database: ' . mysqli_connect_error());
            
        }
        
        if (!$mysqli->set_charset('utf8')) {
            
            $mysqli->close();
            throw new Exception('Can\'t set utf8 to mysqli');
            
        }
            
        $sqlExpdate = $this->haveExpiredDate() ? 'FROM_UNIXTIME(' . $this->expiredDate->format('U') . ')' : 'NULL';
        
        if ($this->id === null) {
            
            if ($this->attachedFile !== null) {
                
                $query = 'INSERT INTO announcements (ann_text, ann_file, ann_expdate) VALUES ("' . $mysqli->escape_string($this->text) . '", "' . $mysqli->escape_string($this->attachedFile->getFilepath()) . '", ' . $sqlExpdate . ')';
                
            } else {
                
                $query = 'INSERT INTO announcements (ann_text, ann_expdate) VALUES ("' . $mysqli->escape_string($this->text) . '", ' . $sqlExpdate . ')';
                
            }
            
            if (!$mysqli->query($query)) {
                
                $mysqli->close();
                throw new Exception('Unsuccessful INSERT query');
                
            }
        
            if ($mysqli->affected_rows === 1) {
                
                $this->id = $mysqli->insert_id;
                
                $mysqli->close();
                
                return true;
                
            } else {
                
                $mysqli->close();
                throw new Exception('No affected rows (or more than 1) after succesful INSERT query');                
                
            }
        
        }
        
        else {

            if ($this->attachedFile !== null) {
                
                $query = 'UPDATE announcements SET ann_text = "' . $mysqli->escape_string($this->text) . '", ann_file = "' . $mysqli->escape_string($this->attachedFile->getFilepath()) . '", ann_expdate = ' . $sqlExpdate . ' WHERE ann_id = ' . $this->id;
                
            } else {
                
                $query = 'UPDATE announcements SET ann_text = "' . $mysqli->escape_string($this->text) . '", ann_expdate = ' . $sqlExpdate . ' WHERE ann_id = ' . $this->id;
                
            }
            
            if (!$mysqli->query($query)) {
                
                $mysqli->close();
                throw new Exception('Unsuccessful UPDATE query');
                
            }
        
            // закомментировано потому, что update без изменений не дает affected_rows
            // if ($mysqli->affected_rows === 1)
            
            $mysqli->close();
             
            return true;	
            
        }        
        
    }
    
    const ACTION_REMOVE = 1;
    const ACTION_RESTORE = 2;
    
    public function deleteMe() {
        
        self::toggleAnnouncement($this->id, self::ACTION_REMOVE);
        
    }
    
    public static function deleteAnnouncement($id) {
        
        self::toggleAnnouncement($id, self::ACTION_REMOVE);
        
    }
    
    public static function restoreAnnouncement($id) {
        
        self::toggleAnnouncement($id, self::ACTION_RESTORE);
        
    }
    
    public static function toggleAnnouncement($id, $concreteAction = null) {
        
        if (!ctype_digit($id)) {
            
            throw new Exception('Announcement id must be numeric');
            
        }
	
        $mysqli = new mysqli(DATABASE_SERVER, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME);
        
        if (mysqli_connect_error()) {
            
            throw new Exception('Can\'t connect to database: ' . mysqli_connect_error());
            
        }
        
        if (!$mysqli->set_charset('utf8')) {
            
            $mysqli->close();
            throw new Exception('Can\'t set utf8 to mysqli');
            
        }
	
        if (!($result = $mysqli->query('SELECT ann_hidden FROM announcements WHERE ann_id = ' . $id)) || $result->num_rows < 1) {
            
            $mysqli->close();
            throw new Exception('Can\'t find announcement with id ' . $id);
            
        }
        
        $row = $result->fetch_assoc();
        $result->free();
        
        if ($row['ann_hidden'] === '1' && $concreteAction === self::ACTION_REMOVE) {
            
            // Уже удалено
            return false;
            
        } elseif ($row['ann_hidden'] === '0' && $concreteAction === self::ACTION_RESTORE) {
            
            // Уже восстановлено
            return false;
            
        }
        
        $toggleHidden = $row['ann_hidden'] === '0' ? '1' : '0';
        
        if (!$mysqli->query('UPDATE announcements SET ann_hidden = ' . $toggleHidden . ' WHERE ann_id = ' . $id) || $mysqli->affected_rows < 1) {
            
            $mysqli->close();
            throw new Exception('Unsuccessful UPDATE query');
            
        }
            
        // Здесь будет помещение в корзину
        
        $mysqli->close();
        
        return true;        
        
    }
    
    public function getHumanReadableExpiredDate() {
        
        return $this->expiredDate->format('j') . ' ' . $GLOBALS['MONTHS_ARRAY'][(int)$this->expiredDate->format('n')] . (($this->expiredDate->format('Y') !== date('Y')) ? ' ' . $this->expiredDate->format('Y') : '');
        
    }
    
    public function getId() {
        
        return $this->id;
        
    }
    
    public function getText() {
        
        return $this->text;
        
    }
    
    public function getFile() {
        
        return $this->attachedFile;
        
    }
    
    public function haveText() {
        
        return !empty($this->text);
        
    }
    
    public function haveAttachedFile() {
        
        return !is_null($this->attachedFile);
        
    }
    
    public function haveExpiredDate() {
        
        return !is_null($this->expiredDate);
        
    }
    
    public function getExpiredDate() {
        
        return $this->expiredDate;
        
    }
    
    public static function separateActualAndNonactual(array $anns) {
        
        $actual = array();
        $nonactual = array();
        
        foreach ($anns as $ann) if ($ann instanceof Announcement) {
            
            if (!$ann->haveExpiredDate() || (int)$ann->getExpiredDate()->format('U') > time()) {
                
                $actual[] = $ann;
                
            } else {
                
                $nonactual[] = $ann;
                
            }
            
        }
        
        return array('actual' => $actual, 'nonactual' => $nonactual);
        
    }
    
    public static function getAnnouncementsFromDatabase($onlyActual = true) {
		
		$anns = array();
		
		$mysqli = new mysqli(DATABASE_SERVER, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME);
	
        if (mysqli_connect_error()) {
            
            throw new Exception('Can\'t connect to database: ' . mysqli_connect_error());
            
        }
        
        if (!$mysqli->set_charset('utf8')) {
            
            $mysqli->close();
            throw new Exception('Can\'t set utf8 to mysqli');
            
        }
	
		if (!($result = $mysqli->query('SELECT * FROM announcements WHERE ann_hidden != 1' . ($onlyActual ? ' AND (ann_expdate > NOW() OR ann_expdate IS NULL)' : '') . ' ORDER BY ann_id DESC'))) {
            
            $mysqli->close();
            throw new Exception('Unsuccessful SELECT query');
            
        }
			
        while ($row = $result->fetch_assoc()) {
            
            try {
                
                $attachedFile = ($row['ann_file'] !== null) ? new AttachedFile($row['ann_file']) : null;
                $expdate      = ($row['ann_expdate'] !== null) ? new DateTime($row['ann_expdate']) : null;
                
                $anns[] = new Announcement($row['ann_text'], $expdate, $attachedFile, $row['ann_id']);
                
            } catch (Exception $e) {
                
                $result->free();
                $mysqli->close();
                
                throw $e;
                
            }
            
        }
        
        $result->free();
        $mysqli->close();
		
		return $anns;
        
    }    
    
}