<?php
/*
 * PHP version 5
 *
 * @copyright Copyright 2010, Cake. (http://trpgtools-onweb.sourceforge.jp/)
 * @category Controller
 * @package  TRPG Data Bank
 * @version  beta
 * @author   Cake <cake_67@users.sourceforge.jp>
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 * @link     http://trpgtools-onweb.sourceforge.jp/
 */

class UsersController extends AppController {

	var $name = 'Users';
	var $helpers = array(
		'Group',
		'Select',
		'Time',
	);

	var $components = array(
		'Mail',
	);

	var $disableTokenActions = array('add');

	// listView用のpagenate設定
	var $paginate = array(
		'conditions' => array(
		),
		'fields' => array(
			'User.id',
			'User.group_id',
			'User.name',
			'User.modified',
		),
		'recursive' => 1,
		'contain' => array(
			'Character',
		),
		'limit' => 20,
		'order' => array(
			'User.id' => 'asc'
		),
	);

	// 検索対象項目
	var $search_cols = array('User.name');

	function beforeFilter() {

		parent::beforeFilter();

		// Cache
		$this->cacheAction = array(
			'view' => Configure::read('Cache.expire'),
			'listview' => Configure::read('Cache.expire'),
		);

		// 認証なしアクセス可
		$this->AuthPlus->allow('index');
		$this->AuthPlus->allow('view');
		$this->AuthPlus->allow('add');
		$this->AuthPlus->allow('regist_end');
		$this->AuthPlus->allow('logout');
		$this->AuthPlus->allow('get_user');
	}

	/* PC */
	function login() {
		// 現在のセッション削除
		$this->AuthPlus->deleteAuth();

		$this->set('title_for_layout', " - ". __('Login', true));
	}

	function logout() {
		self::_logout();
	}

	function regist_end() {
		$this->set('title_for_layout', " - ". __('Regist Mail', true));
	}

	function index() {
		$characters = array();
		if (empty($this->site_configs['Site.myHome']['value']) && $this->params['url']['url'] == '/') {
			$characters = $this->requestAction(
				array('controller' => 'characters', 'action' => 'index'),
				array('return')
			);
		} else {
			// ユーザ情報表示
			if ($this->AuthPlus->user()) {
				$name = $this->user['User']['name'];
				self::_index();
			} else {
				$name = __('Guest', true);
			}
			$this->set('title_for_layout', " - ". sprintf(__("%s's Home", true), $name));

			// 全体の情報
			self::_view($this->user_id);
		}

		$this->set('characters', $characters);

		// お知らせ
		$this->set('news', $this->get_news());
	}

	function view($id = null) {
		if ($id && $id == $this->AuthPlus->user("id")) {
			$this->redirect(array('action'=>'index'));
		}

		$user = $this->getUser($id);
		if (!$user) {
			$this->redirect(array('action'=>'listview'));
		}
		$this->set('target_user', $user);
		$this->set('title_for_layout', " - ". sprintf(__("%s's Home", true), $user['User']['name']));

		$this->set('isOwner', false);

		self::_view($id);
	}

	function listview() {

		self::_listview();
	}

	function search() {

		self::_search(false);
	}

	function add($code = null) {
		// 新規登録停止
		if (!$this->site_configs['User.newUserRegist']['value']) {
			$this->Session->setFlash(__('Unavailable Now.', true));
			$this->redirect(array('action'=>'index'));
		}

		// メールアドレス登録必須
		if ($this->site_configs['User.registMail']['value']) {
			if (empty($code)) {
				$this->redirect(array('controller' => 'regist_mails', 'action'=>'add'));
			}

			$registData = $this->{$this->modelClass}->getRegistData4code($code);
			// $codeに該当するデータなし、user_idに紐づいている
			if (empty($registData) || !empty($registData['RegistMail']['user_id'])) {
				$this->Session->setFlash(__('Invalid URL.', true));
				$this->redirect(array('controller' => 'users', 'action'=>'login'));
			}
		}

		if (!empty($this->data)) {
			self::_add($registData);
		}

		$this->set('code', $code);
		$this->set('idLength', Configure::read('User.UserId.Length'));
		$this->set('passwordLength', Configure::read('User.Password.Length'));

		$this->set('title_for_layout', " - ". __('Add New User', true));
	}

	function edit() {
		// デモモードチェック
		$this->_check_demo();

		$id = $this->AuthPlus->user("id");

		self::_edit($id);

		$this->set('title_for_layout', " - ". __('Edit User', true));
	}

	function edit_image() {
		$id = $this->AuthPlus->user("id");
		$user = $this->getUser($id);

		if (!empty($this->data)) {
			// 重複アップロードチェック
			if (count($this->data['Attachment']) > 2) {
				$this->Session->setFlash(__('Invalid data.', true));
				$this->redirect(array('action'=>'edit_image'));
			}

			if (count($user['Attachment']) == 1) {
				if (!empty($this->data['Attachment'][0])) {
					$this->Session->setFlash(__('Invalid data.', true));
					$this->redirect(array('action'=>'edit_image'));
				}
			}

			$this->data['User']['id'] = $id;

			$fieldList = array(
				'user_id',
				'model',
				'foreign_key',
				'dirname',
				'basename',
				'checksum',
				'size',
				'group',
				'alternative',
				'file',
			);

			if ($this->User->saveAll($this->data, array(
				'validate' => 'first',
				'fieldList' => $fieldList
			))) {
				$this->Session->setFlash(__('The User image has been saved', true));
				$this->redirect(array('action'=>'edit_image'));
			} else {
				$this->Session->setFlash(__('The data could not be saved. Please, try again.', true));
				$this->data['User']['id'] = $id;
			}
		} else {
			$this->data = $user;
		}

		$this->set('title_for_layout', " - ". __('Edit Image', true));
	}

	function edit_mail($code = null) {
		if (empty($code)) {
			$this->Session->setFlash(__('Invalid URL.', true));
			$this->redirect(array('controller' => 'users', 'action'=>'login'));
		}

		$registData = $this->{$this->modelClass}->getRegistData4code($code);

		// $codeに該当するデータなし、user_idが異なる
		if (empty($registData) || empty($registData['RegistMail']['user_id']) || $registData['RegistMail']['user_id'] != $this->user_id) {
			$this->Session->setFlash(__('Invalid URL.', true));
			$this->redirect(array('controller' => 'users', 'action'=>'login'));
		}

		$this->set('title_for_layout', " - ". __('Regist Mail', true));
		self::_edit_mail($registData);
	}

	function change_password() {
		// デモモードチェック
		$this->_check_demo();

		$id = $this->AuthPlus->user("id");
		self::_change_password($id);

		$this->set('passwordLength', Configure::read('User.Password.Length'));

		$this->set('title_for_layout', " - ". __('Change Password', true));
	}

	function delete() {
		// デモモードチェック
		$this->_check_demo();

		$id = $this->AuthPlus->user("id");

		$this->set('title_for_layout', " - ". __('Delete Your Account', true));

		self::_delete($id);
	}

	/* 管理画面 */
	function admin_index() {
		$this->redirect(array('controller' => 'users', 'action'=>'admin_listview'));
	}

	function admin_listview() {
		$this->paginate['fields'] = array_merge($this->paginate['fields'], array(
			'User.username',
			'User.url',
			'User.pcmail',
			'User.useragent',
			'User.host',
			'User.created',
		));

		// 非公開キャラクター取得
		unset($this->User->hasMany['Character']['conditions']['Character.public_flag']);

		// group設定
		$this->paginate['conditions']['User.group_id'] = array(
			Configure::read('Group.admin'),
			Configure::read('Group.subadmin'),
			Configure::read('Group.watcher'),
			Configure::read('Group.member'),
			Configure::read('Group.locked'),
			Configure::read('Group.pre'),
		);

		self::_listview(true);

	}

	function admin_search() {
		$this->search_cols = array_merge($this->search_cols, array('User.notes', 'User.useragent', 'User.host'));

		self::_search(true);
	}

	function admin_view($id = null) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid User.', true));
			$this->redirect(array('controller' => 'users', 'action'=>'index'));
		}

		$user = $this->getUser($id, true);
		if (!$user) {
			$this->redirect(array('action'=>'listview'));
		}
		$user['User'] = $this->decrypt_mail($user['User']);

		$this->set('target_user', $user);

		$this->set('title_for_layout', " - ". $user['User']['name']);
	}

	function admin_add() {
		if (!empty($this->data)) {
			self::_add();
		}

		$this->set('idLength', Configure::read('User.UserId.Length'));
		$this->set('passwordLength', Configure::read('User.Password.Length'));

		$this->set('title_for_layout', " - ". __('Add New User', true));
	}

	function admin_change_password($id = null) {

		if (!$id && empty($this->data)) {
			$this->Session->setFlash(__('Invalid Id.', true));
			$this->redirect(array('controller' => 'users', 'action'=>'index'));
		}
		if (!empty($this->data)) {
			$result = self::_exe_change_password($id);
			if ($result) {
				$this->Session->setFlash(__('The password has been changed.', true));
				$this->redirect(array('controller' => 'users', 'action'=>'index'));
			}
		}
		if (empty($this->data)) {
			$this->data = $this->User->read(null, $id);
		}

		$this->set('passwordLength', Configure::read('User.Password.Length'));
		$this->set('target_user', $this->User->read(null, $id));

		$this->set('title_for_layout', " - ". __('Change Password', true));
	}

	function admin_delete($id = null) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid Id.', true));
			$this->redirect(array('controller' => 'users', 'action'=>'index'));
		}
		if ($this->data) {
			$result = self::_exe_delete($id, true);
			if ($result) {
				$this->redirect(array('controller' => 'users', 'action'=>'index'));
			}
		}

		$user = $this->getUser($id, true, true);
		if (!$user) {
			$this->Session->setFlash(__('No User', true));
			$this->redirect(array('controller' => 'users', 'action'=>'listview'));
		}
		$this->set('target_user', $user);

		$this->data['User']['id'] = $id;

		$this->set('title_for_layout', " - ". __('Delete User', true));
	}

	/* Users共通メソッド */
	function _logout() {
		// キャッシュ削除
		$this->User->deleteCache4User();

		$this->Session->setFlash(__('Logout.', true));
		$this->redirect($this->AuthPlus->logout());
	}

	function _index() {
		$user = $this->user;
		$this->set('target_user', $user);

		$this->set('isOwner', true);
	}

	function _view($id = null) {
		// 指定ユーザの情報
		// characters
		$target_user_characters = array();
		if (!empty($id)) {
			// characters
			$target_user_characters = $this->_get_characters_list4user_id($id, array(), 5, array(), array('System'));
		}
		$this->set('target_user_characters', $target_user_characters);

		// 全体の情報
		$public_characters = array();
		if (empty($id) || ($id == $this->user_id)) {
			// characters
			$public_characters = $this->_get_characters_list4user_id(null, array(), 5, array(), array('System', 'User'));
		}
		$this->set('public_characters', $public_characters);

		$this->set_public_flag4view();
	}

	function _listview($isAdmin = false) {
		if ($isAdmin) {
			$this->paginate['fields'] = array_merge($this->paginate['fields'], array(
				'User.notes',
				'User.username',
				'User.url',
				'User.pcmail',
				'User.useragent',
				'User.host',
				'User.created',
			));

			// 非公開キャラクター取得
			unset($this->User->hasMany['Character']['conditions']['Character.public_flag']);

			// group設定
			$this->paginate['conditions']['User.group_id'] = array(
				Configure::read('Group.admin'),
				Configure::read('Group.subadmin'),
				Configure::read('Group.watcher'),
				Configure::read('Group.member'),
				Configure::read('Group.locked'),
				Configure::read('Group.pre'),
			);

		} else {
			$this->paginate['conditions']['User.group_id'] = array(
				Configure::read('Group.admin'),
				Configure::read('Group.subadmin'),
				Configure::read('Group.watcher'),
				Configure::read('Group.member'),
				Configure::read('Group.locked'),
			);
		}

		$users = $this->paginate();

		if (!empty($users)) {
			foreach ($users as $k => $v) {
				// アドレス復号化
				if (isset($v['User']['pcmail']) && !empty($v['User']['pcmail'])) {
					$users[$k]['User']['pcmail'] = $this->Crypt->decrypt($v['User']['pcmail']);
				}

				// 全キャラクター数取得
				if (empty($v['Character'])) {

					$users[$k]['User']['character_num'] = 0;
				} else {
					$users[$k]['User']['character_num'] = $this->User->Character->find('count', array(
						'conditions' => array_merge($this->User->hasMany['Character']['conditions'],
							array('Character.user_id' => $v['User']['id'])),
						'recursive' => -1,
					));
				}
			}

			$users = $this->HtmlEscape->nl_unescape($users);
		}
		$this->set('users', $users);

		$this->set('title_for_layout', " - ". __('Users List', true));
	}

	function _search($isAdmin = false) {

		// 検索条件設定
		$keywords = null;
		if (isset($this->params['url']['keyword'])) {
			$keywords = rawurldecode($this->params['url']['keyword']);
		}

		$type = 'OR';

		if (!empty($keywords)) {
			$searchwords = explode(",", $keywords);

			$conditions = array();
			foreach ($this->search_cols as $k1 => $search_col) {
				foreach ($searchwords as $k2 => $searchword) {
					if ($k2 != 0) {
						$conditions[$k1] .= ' '. $type. ' ';
					} else {
						$conditions[$k1] = '';
					}

					$conditions[$k1] .= $search_col. ' LIKE '. '\'%'. $searchword. '%\'';
				}
			}

			$this->paginate['conditions']['OR'] = $conditions;

			$searchwords['keywords'] = $keywords;
		} else {
			$searchwords['keywords'] = null;
		}
		$this->set('searchwords', $searchwords);

		self::_listview($isAdmin);
	
		if (isset($keywords)) {
			$this->set('title_for_layout', " - ". $keywords. ' '. __('Search Result', true));
		}
		$this->set('title_for_layout', " - ". __('Search', true));
	}

	function _add($registData = array()) {
		if (!$this->isAdmin) {
			$this->data['User']['group_id'] = Configure::read('Group.member');
			$this->AuthPlus->logout();
		}

		// アドレス登録必須設定
		if ($this->site_configs['User.registMail']['value'] && !$this->isAdmin) {
			if (empty($registData)) {
				$this->redirect(array('controller' => 'regist_mails', 'action'=>'add'));
			}

			if (!empty($registData)) {
				$this->data['User']['pcmail'] = $this->Crypt->decrypt($registData['RegistMail']['mail']);
			}
		}

		// バリデーション
		$this->User->set($this->data);
		if ($this->User->validates()) {
			$fieldList = $this->User->fields['add']; 

			// ACL設定（デフォルト：一般ユーザ）
			if (!isset($this->data['User']['group_id'])) {
				$this->data['User']['group_id'] = Configure::read('Group.member');
			}

			// passwordセット
			$this->data['User']['password'] = $this->AuthPlus->password($this->data['User']['password1']);

			// pcmail
			$fieldList = array_merge($fieldList, array('pcmail'));
			$this->data['User']['pcmail'] = $this->Crypt->crypt($this->data['User']['pcmail']);

			// 他データ
			if (!$this->isAdmin) {
				$this->data['User']['useragent'] = $_SERVER["HTTP_USER_AGENT"];
				$this->data['User']['host'] = gethostbyaddr($_SERVER["REMOTE_ADDR"]);
			}

			// save
			$this->User->create();
			if ($this->User->save($this->data, array('fieldList' => $fieldList, 'validate' => false))) {
				if (!$this->isAdmin) {
					if ($this->site_configs['User.registMail']['value']) {
						if (!empty($registData)) {
							$this->{$this->modelClass}->deleteRegistData4mail($registData['RegistMail']['mail']);
						}
					}

					$this->Session->setFlash(__('The User has been saved. Please Login.', true));
					$this->redirect(array('controller' => 'users', 'action'=>'index'));
				} else {
					$this->Session->setFlash(__('The User has been saved', true));
					
					$this->redirect(array('controller' => 'users', 'action'=>'view', $this->User->id));
				}
			} else {
				$this->Session->setFlash(__('The User cannot be saved.', true));
			}
		}
		if (isset($this->User->validationErrors['pcmail'])) {
			$this->Session->setFlash($this->validationErrors['pcmail']);
			if (!empty($registData)) {
				$this->{$this->modelClass}->deleteRegistData4mail($registData['RegistMail']['mail']);
			}

			$this->redirect(array('controller' => 'users', 'action'=>'index'));
		}
	}

	function _edit($id) {
		if (!empty($this->data)) {
			$this->data['User']['id'] = $id;
			if ($this->User->save($this->data)) {
				$this->Session->setFlash(__('The User has been saved', true));
				$this->redirect(array('action'=>'index'));
			} else {
				$this->Session->setFlash(__('The data could not be saved. Please, try again.', true));
			}
		}
		if (empty($this->data)) {
			$this->data = $this->User->read(null, $id);

			$this->data['User'] = $this->_restore_html_user($this->data['User'], true);
		}
	}

	function _edit_mail($registData = array()) {
		$data['User']['pcmail'] = $registData['RegistMail']['mail'];
		$fields = array('pcmail');

		// validate
		$data['User']['id'] = $this->user_id;
		if ($this->User->save($data, array('fieldList' => $fields, 'validate' => false))) {
				$this->{$this->modelClass}->deleteRegistData4mail($registData['RegistMail']['mail']);

				$this->Session->setFlash(__('The User has been saved', true));
				$this->redirect(array('action'=>'index'));
		}

		$this->Session->setFlash(__('The data could not be saved. Please, try again.', true));
		$this->redirect(array('action'=>'index'));
	}

	function _change_password($id) {
		if (!empty($this->data)) {
			$data = $this->User->read('password', $id);
			if ($data['User']['password'] != $this->AuthPlus->password($this->data['User']['password'])) {
				$this->Session->setFlash(__('Old Password is wrong.', true));
			} else {
				$result = self::_exe_change_password($id);
				if ($result) {
					$this->Session->setFlash(__('The password has been changed. Please login at new password.', true));
					$this->redirect($this->AuthPlus->logout());
				}
			}
		}
	}
	function _exe_change_password($id) {
		// バリデーション
		$this->User->set($this->data);
		if ($this->User->validates()) {
			$this->data['User']['id'] = $id;

			// passwordセット
			$this->data[$this->AuthPlus->userModel]['password'] = $this->AuthPlus->password($this->data[$this->AuthPlus->userModel]['password1']);

			if ($this->User->save($this->data, array('fieldList' => array('password')))) {
				return true;
			} else {
				$this->Session->setFlash(__('The data could not be saved. Please, try again.', true));
				return false;
			}
		}
	}

	function _delete($id) {
		if ($this->data) {
			$data = $this->User->read('password', $id);
			if ($data['User']['password'] != $this->AuthPlus->password($this->data['User']['password'])) {
				$this->Session->setFlash(__('Password is wrong.', true));
			} else {
				$result = self::_exe_delete($id, false);
				if ($result) {
					$this->redirect($this->AuthPlus->logout());
				} else {
					$this->redirect(array('action'=>'index'));
				}
			}
		}
	}
	function _exe_delete($id, $isAdmin=false) {
		$user = $this->getUser($id, $isAdmin, true);
		if (!$user) {
			return false;
		}
		if ($user['User']['group_id'] == Configure::read('Group.admin')) {
			$this->Session->setFlash(__('Super Administrator can not be deleted.', true));
			return false;
		}

		if ($isAdmin) {
			$this->data['User']['id'] = $id;
			$this->data['User']['group_id'] = Configure::read('Group.deleted');

			$this->User->create();
			$result = $this->User->save(
					$this->data,
					array(
						'validate' => false,
						'fieldList' => array(
							'group_id',
						),
					)
			);
		} else {
			$result = $this->User->delete($id);
		}

		if ($result) {
			if (!empty($user['Character'])) {
				App::import('Controller', 'Characters');
				$this->CharactersController = new CharactersController;
				$this->CharactersController->Character = CorePlus::set_model('Character');
				$this->CharactersController->Session = new SessionComponent;
				$this->CharactersController->data['Character'] = $this->data['Character'];

				foreach ($user['Character'] as $character) {
					$this->CharactersController->_delete($character['id'], array(), true);
				}
			}
			$this->Session->setFlash(sprintf(__('%s was deleted.', true), $user['User']['name']));
			return true;
		} else {
			$this->Session->setFlash(__('The account could not be deleted.', true));
			return false;
		}
	}

	// ログインユーザ取得
	function get_user() {
		return $this->user;
	}
}

