<?

//статусы
//0 - отправлено
//1 - удалено отправителем
//2 - удалено получателем

class lc_pm_message extends ModuleTools
{
	public $sender_id=null;
	public $receiver_id=null;
	public $user_id=null;
	public $inbox=true;
	public $max_outbox=250;
	public $max_inbox=250;
	
	function __construct()
	{
		$this->user_id=User::i()->id;
		if (LabConfig::$mcfg['max_outbox']) $this->max_outbox=LabConfig::$mcfg['max_outbox'];
		if (LabConfig::$mcfg['max_inbox']) $this->max_inbox=LabConfig::$mcfg['max_inbox'];
	}
	
	public function send($receiver_id, $subj, $msg)
	{
		$this->sender_id=$this->user_id;
		$this->receiver_id=$receiver_id;
		
		$this->subj=$subj;
		$this->msg=$msg;
		
		if ($this->check_msg())
		{
			$this->status=$this->getStatus();
			if ($this->id=$this->_send())
			{
				if (!$this->status) $this->updateUserCounter($this->receiver_id, 1, 1);
				return true;
			}
		}
		return false;
	}
	
	public function sendSystem($receivers, $subj=false, $msg=false)
	{
		if (!is_array($receivers)) $receivers=array($receivers);
		if ($subj) $this->subj=$subj;
		if ($msg) $this->msg=$msg;
		$this->receiver_id=$receivers;
		
		if ($this->check_msg())
		{
			$this->sender_id=0;
			if ($this->_send())
			{
				$this->updateUserCounter($this->receiver_id, 1, 1);
				return true;
			}
		}
		return false;
	}
	
	public function isSendPossible($user_id)
	{
		if (!$this->isSenderAvalible()) return false;
		if (!$this->isReceiverAvalible($receiver)) return false;
		return true;
	}
	
	protected function _send()
	{
		if (is_array($this->receiver_id))
		{
			return Db::i()->query("INSERT INTO ?_lc_pm (sender_id, receiver_id, subj, msg, putdate, `status`) VALUES".$this->prepareMultipleData());
		}
		else
		{
			return Db::i()->query("INSERT INTO ?_lc_pm (sender_id, receiver_id, subj, msg, putdate, `status`) VALUES(?, ?, ?, ?, NOW(), ?)", $this->sender_id, $this->receiver_id, $this->subj, $this->msg, $this->status);
		}
	}
	
	protected function prepareMultipleData()
	{
		$data=array();
		foreach($this->receiver_id as $id)
		{
			$data[]="("
			.$this->sender_id.","
			.$id.","
			."'".mysql_real_escape_string($this->subj)."',"
			."'".mysql_real_escape_string($this->msg)."',"
			."NOW(),"
			."1"
			.")";
		}
		return implode(",", $data);
	}
	
	function updateUserCounter($user_id, $mess_cnt=1, $umess_cnt=1)
	{
		if (empty($user_id)) return false;
		if (!is_array($user_id)) $user_id=array($user_id);
		if (count($user_id)!=Db::i()->query("UPDATE ?_lc_pm_stat SET mess=mess+?d, umess=umess+?d WHERE user_id IN (?a)", $mess_cnt, $umess_cnt, $user_id))
		{
			foreach($user_id as $id)
			{
				Db::i()->query("INSERT IGNORE INTO ?_lc_pm_stat (user_id, mess, umess) VALUES(?, ?, ?)", $id, $mess_cnt, $umess_cnt);
			}
		}
	}
	
	function isSenderAvalible()
	{
		if (Db::i()->selectCell("SELECT COUNT(mess_id) FROM ?_lc_pm WHERE sender_id=? AND `status` IN (?a)", $this->user_id, lc_pm::$out_statuses)>=$this->max_outbox)
		{
			return self::_error("Ваш ящик исходящих сообщений переполнен. Вы не можете отправлять сообщения.");
		}
		return true;
	}
	
	function isReceiverAvalible($user_id)
	{
		$info=Db::i()->selectRow("SELECT mess, login 
									FROM ?_lc_pm_stat ms 
									JOIN ?_users u ON ms.user_id=u.user_id 
									WHERE u.user_id=? AND group_id>0 AND `status`>0", $user_id);
		if ($info===false) return self::_error("Пользователь не найден.");
		if ($info['mess']>=$this->max_inbox)	return self::_error("Ящик пользователя переполнен - он не сможет получить Ваше сообщение.");
		$this->receiver=$info['login'];
		return true;
	}
	
	function getStatus()
	{
		//если в списке игнорирования - возвращаем статус "удалено получателем"
		return (Db::i()->selectCell("SELECT user_id FROM ?_lc_pm_ignore WHERE ignore_id=? AND user_id=?", $this->sender_id, $this->receiver_id))?2:0;
	}
	
	function check_msg()
	{
		if (!trim($this->subj)) self::_error("Тема письма не может быть пустой");
		if (!trim($this->msg)) self::_error("Сообщение не может быть пустым");
		if (mb_strlen($this->msg)>2048) self::_error(sprintf(_m("Сообщение слишком длинное. Максимальная длина сообщения %s"), '2Kb'), true);
		return LabCMS::i()->no_errors;
	}
	
	function getMessage($mess_id)
	{
		if ($this->inbox) //если папка входящих
		{
			$msg=Db::i()->selectRow("SELECT mess_id, msg, subj, sender_id, unread, login as sender, putdate
											FROM ?_lc_pm m 
											LEFT JOIN ?_users u ON m.sender_id=u.user_id 
											WHERE mess_id=? AND receiver_id=? AND m.status IN (?a)", 
											$mess_id, $this->user_id, lc_pm::$in_statuses);
			if ($msg)
			{
				if ($msg['unread'])
				{
					Db::i()->query("UPDATE ?_lc_pm SET unread=0 WHERE mess_id=?", $msg['mess_id']);
					$msg['unread']=0;
					$this->updateUserCounter($this->user_id, 0, -1);
				}
				
				if($msg['sender_id'])
				{
					$this->history=Db::i()->select("SELECT msg, subj, sender_id, putdate 
													FROM ?_lc_pm
													WHERE ((sender_id=? AND receiver_id=?)
													OR (sender_id=? AND receiver_id=?))
													AND mess_id<?d
													ORDER BY mess_id DESC LIMIT 10",
													$msg['sender_id'], $this->user_id, $this->user_id, $msg['sender_id'], $msg['mess_id']);
					
					if ($this->history) foreach($this->history as $key=>$item)
					{
						$this->history[$key]['msg_html']=getbb($item['msg']);
						if ($item['sender_id']==$msg['sender_id'])
						{
							$this->history[$key]['login']=$msg['sender'];
						}
						else
						{
							$this->history[$key]['login']=User::i()->login;
							$this->history[$key]['my']=true;
						}
					}
				}
			}
		}
		else //если папка исходящих
		{
			$msg=Db::i()->selectRow("SELECT mess_id, msg, subj, receiver_id, login as receiver, putdate
											FROM ?_lc_pm m
											JOIN ?_users u ON m.receiver_id=u.user_id
											WHERE mess_id=? AND sender_id=? AND m.status IN (0, 2)",
											$_GET['var1'], $this->user_id);
		}

		if ($msg)
		{
			$this->id=$msg['mess_id'];
			$this->next=$this->getNext();
			$this->prev=$this->getPrev();
			$msg['msg_html']=getbb($msg['msg']);
			return $msg;
		}
		return self::_error("Сообщение не найдено!");
	}
	
	function getReply($mess_id)
	{
		$msg=Db::i()->selectRow("SELECT mess_id, msg, subj, sender_id, login FROM ?_lc_pm m JOIN ?_users u ON m.sender_id=u.user_id WHERE mess_id=? AND receiver_id=?", $mess_id, $this->user_id);
		
		if (!$msg) return self::_error("Сообщение не найдено");
		
		if (!$this->isSenderAvalible($this->user_id)) return;
		if (!$this->isReceiverAvalible($msg['sender_id'])) return;
		
		preg_match('/^RE(\[(\d+)\])?:/is', $msg['subj'], $subj_tmp);
		if (!empty($subj_tmp[2])) $msg['subj']=preg_replace('/^'.preg_quote($subj_tmp[0], '/').'/', 'RE['.($subj_tmp[2]+1).']:', $msg['subj']);
		elseif(!empty($subj_tmp[0])) $msg['subj']=preg_replace('/^RE/', 'RE[2]', $msg['subj']);
		else $msg['subj']='RE: '.$msg['subj'];
		
		$this->history=Db::i()->select("SELECT msg, subj, sender_id, putdate FROM ?_lc_pm WHERE ((sender_id=? AND receiver_id=?) OR (sender_id=? AND receiver_id=?)) ORDER BY mess_id DESC LIMIT 10", $msg['sender_id'], $this->user_id, $this->user_id, $msg['sender_id']);
		if ($this->history) foreach($this->history as $key=>$item)
		{
			$this->history[$key]['msg_html']=getbb($item['msg']);
			if ($item['sender_id']==$msg['sender_id'])
			{
				$this->history[$key]['login']=$msg['login'];
			}
			else
			{
				$this->history[$key]['login']=User::i()->login;
				$this->history[$key]['my']=true;
			}
		}
		return $msg;
	}
	
	
	function deleteMessage($msg)
	{
		if (!$msg) return false;
		if (!is_array($msg)) $msg=array($msg);
		$messsages=Db::i()->select("SELECT mess_id AS ARRAY_KEY, sender_id, receiver_id, status, unread FROM ?_lc_pm WHERE mess_id IN (?a) AND (sender_id=? OR receiver_id=?)", $msg, $this->user_id, $this->user_id);
		
		/*
		$delete - сообщения подлежащие полному удалению
		$updateS - сообщения, которые нужно убрать из отправленных
		$updateR - сообщения, которые нужно убрать из принятых
		$undead - непрочитанные сообщения которые удалены из входящих
		$total - всего сообщений которые удалены из входящих
		*/
		
		$delete=$updateS=$updateR=array();
		$total=$unread=0;
		foreach($messsages as $msg_id=>$msg)
		{
			//удаляем из отправленных
			if ($msg['sender_id']==$this->user_id && !$this->inbox)
			{
				//если сообщение не удалено
				if ($msg['status']==0) $updateS[]=$msg_id;
				//если сообщение удалено получателем
				if ($msg['status']==2) $delete[]=$msg_id;
			}
			//удаляем из принятых
			if ($msg['receiver_id']==$this->user_id && $this->inbox)
			{
				//если сообщение не удалено
				if ($msg['status']==0) $updateR[]=$msg_id;
				//если сообщение удалено отправителем
				if ($msg['status']==1) $delete[]=$msg_id;
				
				if ($msg['unread']) $unread++;
				$total++;
			}
		}

		if (count($updateS)) Db::i()->query("UPDATE ?_lc_pm SET status=1 WHERE mess_id IN (?a)", $updateS);
		if (count($updateR)) Db::i()->query("UPDATE ?_lc_pm SET status=2 WHERE mess_id IN (?a)", $updateR);
		if (count($delete)) Db::i()->query("DELETE FROM ?_lc_pm WHERE mess_id IN (?a)", $delete);
		//exit;
		if ($total) $this->updateUserCounter($this->user_id, -$total, -$unread);
		return (count($updateS)+count($updateR)+count($delete));
	}
	
	public function getNext()
	{
		if ($this->inbox)
		{
			return Db::i()->selectCell("SELECT MAX(mess_id)
												FROM ?_lc_pm 
												WHERE receiver_id=? AND mess_id<?  AND status IN (?a)",
												$this->user_id, $this->id, lc_pm::$in_statuses);
		}
		else
		{
			return Db::i()->selectCell("SELECT MAX(mess_id)
													FROM ?_lc_pm
													WHERE sender_id=? AND mess_id<? AND status IN (?a)",
													$this->user_id, $this->id, lc_pm::$out_statuses);
		}
	}
	
	public function getPrev()
	{
		if ($this->inbox)
		{
			return Db::i()->selectCell("SELECT MIN(mess_id)
												FROM ?_lc_pm
												WHERE receiver_id=? AND mess_id>?  AND status IN (?a)",
												$this->user_id, $this->id, lc_pm::$in_statuses);
		}
		else
		{
			return Db::i()->selectCell("SELECT MIN(mess_id)
													FROM ?_lc_pm
													WHERE sender_id=? AND mess_id>? AND status IN (?a)",
													$this->user_id, $this->id, lc_pm::$out_statuses);
		}
	}

}