<?php
/**
 * 部屋に関する情報と部屋に対する一般的な操作を提供します。
 */
class ChatRoom {
  var $db;

  var $id;
  var $name;
  var $comment;
  var $max_users;
  var $is_active;
  var $internal_time;
  var $status;
  var $built_time;
  var $builder_ip;
  var $last_updated_time;
  var $login_user;
  private $_options = array();

  var $last_alarm_type;
  var $last_alarm_time;
  var $last_alarm_itime;
  var $last_alarm_message;

  var $players = array();
  var $log = array();

  var $_filters = array();
  private $load_stmt;
  /*
  var $id;
  var $name;
  var $comment;
  var $game_option = '';
  var $option_role = '';
  var $date;
  var $day_night;
  var $status;
  var $system_time;
  var $sudden_death;
  var $view_mode = false;
  var $dead_mode = false;
  var $heaven_mode = false;
  var $log_mode = false;
  var $watch_mode = false;
  var $single_view_mode = false;
  var $test_mode = false;
   */


  /**
   * データベース接続を指定して、ChatRoomクラスの新しいインスタンスを初期化します。
   * @param ChatEngine $engine 有効なデータベース接続を保持したChatEngineオブジェクト
   */
  function __construct($engine) {
    $this->db = $engine;
  }

  /**
   * 名前と値を指定して、オブジェクトに未定義のプロパティを設定します。
   * @param <type> $name
   * @param <type> $value
   */
  function __set($name, $value) {
    switch($name) {
      case 'options':
        if (is_array($value)) {
          $this->_options = $value;
        }
        if (is_string($value)) {
          $this->_options = unserialize($value);
        }
        break;
      case 'game_option':
      case 'option_role':
        if (is_string($value)) {
          $this->_options[$name] = explode(',', $value);
        }
        else {
          $this->_options[$name] = $value;
        }
        break;
      case 'description':
        $this->comment = $value;
        break;
    }
  }

  function  __get($name) {
    switch ($name) {
      case 'options':
        return $this->_options;
      case 'game_option':
      case 'option_role':
        return isset($this->_options[$name]) ? $this->_options[$name] : array();
    }
  }

  /**
   * ゲームが昼のターンかどうか確認します。
   */
  function IsDay($containsTimeover = true){
    $time = $this->internal_time % 10000000;
    return $containsTimeover
      ? $time < 1000000
      : 0060000 <= $time && $time < 0180000;
  }

  /**
   * ゲームが夜のターンかどうか確認します。
   */
  function IsNight($containsTimeover = true){
    $time = $this->internal_time % 10000000;
    return $containsTimeover
      ? 1000000 <= $time
      : 1180000 <= $time && $time < 1300000; //Note:深夜30時 (2011-06-12 enogu)
  }

  /**
   * ゲームの開始前かどうか確認します。
   */
  function IsBeforeGame(){
    return $this->internal_time < 10000000;
  }

  /**
   * ゲームが終了しているかどうか確認します。
   */
  function IsAfterGame(){
    return !$this->is_active && (10000000 <= $this->internal_time);
  }

  /**
   * ゲーム中かどうか確認します。
   * このメソッドは仮想処理をする為、status では判定しません
   */
  function IsPlaying(){
    return $this->is_active;
  }

  /**
   * ゲームが終了しているかどうか確認します。
   */
  function IsFinished(){
    return !$this->is_active;
  }

  /**
   * 現在のユーザーに関連づけられているセッションIDとIPアドレスを最新のものに更新します。
   * @return bool 更新に成功したらtrue,それ以外の場合false
   */
  function UpdateSessionInfo() {
    $sql = 'UPDATE jinrou_users SET session_id = :session_id, ip_address = :ip_address WHERE id = :uid';
    if (($stmt = $this->db->prepare($sql)) !== false) {
      $retry = 3;
      while ($retry--) {
        $bindings = array(
          ':session_id' => session_id(),
          ':ip_address' => $_SERVER['REMOTE_ADDR'],
          ':uid' => $this->login_user
        );
        if ($stmt->execute($bindings)) {
          return true;
        }
        session_regenerate_id();
      }
    }
    return false;
  }

  /**
   * 現在村に存在しているプレイヤーのリストを読み込みます。
   * @param string $class 読み込まれたプレイヤーオブジェクトの型を文字列で指定します。
   * @return boolean 成功した場合true、それ以外の場合false
   */
  function LoadPlayers($class = 'ChatUser') {
    $sql = <<<SQL
SELECT
  ply.id AS id,
  ply.user AS user_id,
  ply.user_no,
  usr.uname,
  ply.handle_name,
  ply.profile,
  ply.sex,
  ply.live,
  ply.role
FROM jinrou_players AS ply
  INNER JOIN (
    SELECT
      MAX(p.id) AS id
    FROM jinrou_users AS u
      INNER JOIN jinrou_players AS p ON u.id = p.user
    WHERE u.room = :room_id
      AND p.live IN ('live', 'dead')
    GROUP BY p.user_no
  ) AS visible
    ON ply.id = visible.id
  INNER JOIN jinrou_users AS usr ON ply.user = usr.id
ORDER BY ply.user_no
SQL;
    if (($stmt = $this->db->prepare($sql)) !== false) {
      $stmt->bindValue(':room_id', $this->id, PDO::PARAM_INT);
      if ($stmt->execute()) {
        $players = array();
        foreach($stmt->fetchAll(PDO::FETCH_CLASS, $class, array($this->db)) as $player) {
          $players[$player->user_no] = $player;
        }
        $this->players = $players;
        return true;
      }
    }
    return false;
  }
}
