<?php
/*
* @package LabCMS
* @copyright (c) 2006 Alexander Levin aka Loki (loki_angel@mail.ru)
* @support http://labcms.ru
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/

class lc_comments_item extends DefaultObject
{
	const default_type=1;
	protected $allowed_keys=array('url', 'title', 'counter');
	
	public function __construct($id=null)
	{
		$this->data['id']=&$this->data['item_id'];
		if ($id) $this->loadDataById($id);
	}
	
	public function loadDataByKey($key, $url, $title, $type=self::default_type)
	{
		if ($data=TCache::get('comments_item_type_'.$type.'_key_'.$key)) {
			$this->set($data);
			$cached=true;
		}
		
		if (!$this->id) {
			$cached=false;
			if ($data=Db::i()->selectRow(
				"SELECT * FROM ?_comments_items WHERE `key`=? AND module_id=?", $key, LabCMS::i()->getModuleId()
			)) {
				$this->set($data);
			} else {
				$obj=$this->add($key, $url, $title);
				$this->loadDataById($obj->id);
			}
		}
		
		$update=array();
		if ($url && $this->url!=$url) $update['url']=$url;
		if ($title && $this->title!=$title) $update['title']=$title;
		if (count($update)) $this->update($update);
		
		if (!$cached) {
			TCache::set($this->data, 'comments_item_type_'.$type.'_key_'.$key, array('comments_item_id_'.$this->id));
		}

	}
	
	public function loadDataById($id)
	{
		if (!$data=TCache::get('comments_item_id_'.$id)) {
			if ($data=Db::i()->selectRow("SELECT * FROM ?_comments_items WHERE item_id=?", $id)) {
				$this->set($data);
				TCache::set($data, 'comments_item_id_'.$id, array('comments_item_id_'.$id));
			}
		}
	}

	public function getComments()
	{
		if (!$this->counter) return;
		if (!$this->comments) {
			$list=Factory::create('lc_comments.list');
			$this->comments=$list->getCommentsByItem($this);
		}
		
		foreach ($this->comments as $comment) {
			$comment->setAccesses();
		}
		
		return $this->comments;
	}
	
	public function getUserItemVotes()
	{
		if (User::i()->isGuest()) return;
		if (!$this->counter) return;
		if (config::get('module.lc_comments.rating_enable')) {
			$voter=Rating_Generic::init();
			$ids=array();
			foreach ($this->comments as $comment) {
				$ids[]=$comment->id;
			}
			return $voter->getUserItemVotes($ids, $comment->getVoteType());
		}
	}
	
	public function changeCounter($count=1)
	{
		$this->update(array('counter'=>$this->counter+$count));
	}
	
	public function addComment($data, $parent=null)
	{
		if (!$parent) {
			$left_key=$this->_getMaxKey()+1;
			$level=1;
			$parent_id=0;
		} else {
			$left_key=$parent->right_key;
			$level=$parent->level+1;
			$parent_id=$parent->id;
		}
		$right_key=$left_key+1;
		
		$data=array(
			'parent_id'=>$parent_id,
			'item_id'=>$this->id,
			'text'=>$data['text'],
			'putdate'=>time(),
			'updated'=>time(),
			'ip'=>inet_pton(User::i()->getIP()),
			'user_id'=>User::i()->isGuest()?null:User::i()->id,
			'login'=>User::i()->isGuest()?$data['login']:null,
			'email'=>User::i()->isGuest()?$data['email']:null,
			'status'=>$data['status'],
			'left_key'=>$left_key,
			'right_key'=>$right_key,
			'level'=>$level,
		);

		$data['comment_id']=Db::i()->query(
			"INSERT INTO ?_comments
			(?#)
			VALUES(?a)",
			array_keys($data),
			array_values($data)
		);
		
		if ($data['comment_id']) {
			Db::i()->query(
				"UPDATE ?_comments
				SET right_key=right_key+2,
				left_key=IF(left_key>?,
				left_key+2, left_key)
				WHERE right_key>=? AND comment_id!=? AND item_id=?",
				$data['left_key'], $data['left_key'], $data['comment_id'], $this->id
			);
			$comment=Factory::create('lc_comments.comment', $data['comment_id']);

			$this->changeCounter(1);
			return $comment;
		}
	}
	
	public function add($key, $url, $title)
	{
		$item=array('key'=>$key,
		            'url'=>$url,
					'title'=>$title,
		            'module_id'=>LabCMS::i()->getModuleId()
		);
		$item['item_id']=Db::i()->query(
			"INSERT IGNORE INTO ?_comments_items (?#) VALUES(?a)",
			array_keys($item), array_values($item)
		);
		
		if ($item['item_id']) {
			$item['comments']=array();
			$item['last_update']=time();
			$item['counter']=0;
			$obj=new self();
			$obj->set($item);
			return $obj;
		}
	}
	
	public function delete()
	{
		//TODO этот фрагмент переписать чтобы удалением занимался класс list
		if ($comments=Db::i()->selectCol("SELECT comment_id FROM ?_comments WHERE item_id=?", $this->id)) {
			Db::i()->query("DELETE FROM ?_comments WHERE item_id=?", $this->id);
			$comments=Factory::create('lc_comments.list');
			$comments->_resetItemCache();
		}
		Db::i()->query("DELETE FROM ?_comments_items WHERE item_id=?", $this->id);
	}
	
	protected function _updateDB(&$data)
	{
		return Db::i()->query("UPDATE ?_comments_items SET ?a WHERE item_id=?", $data, $this->id);
	}
	
	protected function _resetItemCache()
	{
		TCache::remove('comments_item_type_'.$this->type.'_key_'.$this->key);
		TCache::remove('comments_item_id_'.$this->id);
	}
	
	public function getItemsByIds($ids)
	{
		$ids=array_unique($ids);
		$result=array();
		if ($data=Db::i()->select("SELECT * FROM ?_comments_items WHERE item_id IN(?a)", $ids)) {
			foreach ($data as $item) {
				$result[$item['item_id']]=new self();
				$result[$item['item_id']]->set($item);
			}
		}
		return $result;
	}
	
	protected function _getMaxKey()
	{
		return intval(
			Db::i()->selectCell(
				"SELECT MAX(right_key)
				FROM ?_comments WHERE item_id=?",
				$this->id
			)
		);
	}
	
	public function checkStructure()
	{
		$result=Db::i()->selectCol(
			"SELECT comment_id FROM ?_comments
			WHERE left_key>=right_key AND item_id=?", $this->id
		);
		if ($result) return 'Элементы с левым ключом больше правого: '.implode(', ', $result);
		
		/*$result=Db::i()->selectRow(
			"SELECT COUNT(comment_id) as total, MIN(left_key) as min_key, MAX(right_key) as max_key 
			FROM ?_comments WHERE item_id=?", $this->id);
		if ($result['min_key']!==1) return 'Миннимальный ключ равен '.$result['min_key'];
		if ($result['max_key']!=($result['total']*2-1))
		return 'Максимальный ключ равен '.$result['max_key'].' и не равен '.($result['total']*2-1);*/
		
		$result=Db::i()->select(
			"SELECT comment_id, MOD((right_key-left_key), 2) AS ostatok
			FROM ?_comments WHERE item_id=? HAVING ostatok=0", $this->id
		);
		
		if ($result) return print_r($result, true);
		
		$result=Db::i()->select(
			"SELECT comment_id, MOD((left_key-level+2), 2) AS ostatok
			FROM ?_comments HAVING ostatok=0"
		);
		
		if ($result) print_r($result, true);
		
		$result=Db::i()->select(
			"SELECT t1.comment_id, COUNT(t1.comment_id) AS rep,
			MAX(t3.right_key) AS max_right
			FROM ?_comments AS t1, ?_comments AS t2, ?_comments AS t3
			WHERE t1.left_key <> t2.left_key
			AND t1.left_key <> t2.right_key
			AND t1.right_key <> t2.left_key
			AND t1.right_key <> t2.right_key
			AND t1.item_id=t2.item_id
			AND t2.item_id=t3.item_id
			AND t3.item_id=?
			GROUP BY t1.comment_id
			HAVING max_right <> SQRT(4 * rep + 1) + 1 ", $this->id
		);
		if ($result) return print_r($result, true);
		
		return false;
	}
}