<?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 CharacterSheetsController extends AppController {

	var $name = 'CharacterSheets';
	var $helpers = array(
		'Select',
		'Profiledisp',
	);

	// pagenate設定
	var $paginate = array(
		'conditions' => array(
		),
		'fields' => array(
		),
		'recursive' => 1,
		'contain' => array(
			'System',
			'User',
		),
		'limit' => 20,
		'order' => array(
			'CharacterSheet.modified' => 'desc',
		),
	);

	var $disableTokenActions = array();

	/* メソッド */

	function beforeFilter() {

		parent::beforeFilter();

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

		// 認証なしアクセス可
		$this->AuthPlus->allow('skinsample');
	}

	function beforeRender()
	{
		parent::beforeRender();

		$this->set_public_flag4view();
	}

	/* アクションメソッド */

	function index($system_id = null) {
		// Check
		$this->_checkCharaSheeAuth($system_id);

		// user_id指定
		if (isset($this->passedArgs['user_id']) && !empty($this->passedArgs['user_id'])) {
			$user_id = $this->passedArgs['user_id'];
			if ($user_id == $this->user_id) {
				$this->redirect(array('action' => 'myindex', $system_id));
			}
		} else {
			$user_id = null;
		}

		$this->paginate['conditions']['CharacterSheet.public_flag'] = 1;


		$this->_index($system_id, $user_id, false);
	}

	function myindex($system_id = null) {
		// Check
		$this->_checkCharaSheeAuth($system_id);

		$this->_index($system_id, $this->user_id, false);
	}

	function admin_index($system_id = null) {
		// user_id指定
		if (isset($this->passedArgs['user_id']) && !empty($this->passedArgs['user_id'])) {
			$user_id = $this->passedArgs['user_id'];
		} else {
			$user_id = null;
		}

		$this->_index($system_id, $user_id, true);
	}

	function _index($system_id = null, $user_id = null, $isAdmin = false) {
		$title = __('List of All CharacterSheets', true);

		// $system_id指定
		if (!empty($system_id)) {
			// System情報取得
			$this_system = $this->__getThisSystem($system_id, $isAdmin);
			$this->set('this_system', $this_system);

			// character_sheets絞込み
			$this->paginate['conditions']['CharacterSheet.system_id'] = $system_id;
			if (empty($isAdmin)) {
				$this->paginate['conditions']['System.public_flag'] = 1;
			}

			$title = $this_system['System']['name']. ' '. $title;
		}

		// user_id指定
		if (!empty($user_id)) {
			$user = $this->getUser($user_id);

			if (empty($user)) {
				$this->Session->setFlash(__('Invalid Id.', true));
				$this->redirect(array('action'=>'index'));
			}
			$this->set('target_user', $user);

			// character_sheets絞込み
			$this->paginate['conditions']['CharacterSheet.user_id'] = $user_id;

			if ($isAdmin || $user_id == $this->user_id) {
				unset($this->paginate['conditions']['CharacterSheet.public_flag']);
			}

			$title = sprintf(__("%s's", true), $user['User']['name']). ' '. $title;
		}

		$characterSheets = $this->paginate();

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

		$this->set('title_for_layout', " - ". $title);
	}

	function view($id = null) {
		// Check
		$this->_checkCharaSheeAuth();

		$this->_view($id , false);
	}

	function admin_view($id = null) {

		$this->_view($id , true);
	}

	function _view($id = null, $isAdmin = true) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid CharacterSheet.', true));
			$this->redirect(array('action'=>'index'));
		}

		$contain = array(
			'System' => array(
				'Character',
			),
		);
		if ($isAdmin) {
			$contain[] = 'User';
		}

		$characterSheet = $this->CharacterSheet->find('first', array(
			'conditions' => array('CharacterSheet.id' => $id),
			'fields' => '',
			'recursive' => 2,
			'contain' => $contain,
		));
		$characterSheet = $this->__restore_html_system($characterSheet);
		
		if (empty($characterSheet)) {
			$this->Session->setFlash(__('Invalid CharacterSheet.', true));
			$this->redirect(array('action'=>'index'));
		}
		// 一般ユーザの場合、自身のキャラシのみ
		if (empty($isAdmin)) {
			$this->__checkCharaSheeOwner($characterSheet);
		}

		$this->set('characterSheets', $characterSheet);

		// キャラシビュー表示
		$skin_dir = $this->getSkinDir($characterSheet['CharacterSheet']['key_name']);
		$view_link = null;
		if (is_readable($skin_dir. 'view.ctp') && !empty($characterSheet['System']['Character'])) {
			$view_link = Router::url(array(
				'controller' => 'characters',
				'action' => 'view',
				'prefix' => Configure::read('Routing.base_prefixes'),
				$characterSheet['System']['Character'][0]['id'],
				'mode:'. $characterSheet['CharacterSheet']['key_name']), true
			);
		}
		$this->set('view_link', $view_link);


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

	function add($system_id = null) {
		// Check
		$this->_checkCharaSheeAuth($system_id);

		$this->_add($system_id, false);
	}


	function admin_add($system_id = null) {

		$this->_add($system_id, true);
	}

	function _add($system_id = null, $isAdmin = false) {
		if (empty($isAdmin)) {
			$systems = $this->_get_systems(1);
		} else {
			$systems = $this->_get_systems(null);
		}
		$this->set(compact('systems'));

		// System情報取得
		$this_system = array();
		if (!empty($system_id)) {
			if (!empty($this->data)) {
				$this->data['CharacterSheet']['system_id'] = $system_id;
			}
			$this_system = $this->__getThisSystem($system_id, $isAdmin);
		}
		$this->set('this_system', $this_system);

		if (!empty($this->data)) {
			$this->data['CharacterSheet']['user_id'] = $this->user_id;

			// Dir作れなかった場合のロールバック用
			$dataSource = $this->CharacterSheet->getDataSource();
			$dataSource->begin($this);

			$this->CharacterSheet->create();
			if ($this->CharacterSheet->save($this->data, array('fieldList' => $this->CharacterSheet->fields['add']))) {

				$new_dir = $this->getSkinDir($this->data['CharacterSheet']['key_name']);
				if (@mkdir($new_dir, 0777, true)) {
					$this->Session->setFlash(__('The CharacterSheet has been saved', true));
					$dataSource->commit($this);
				} else {
					$this->Session->setFlash(__('The new directory  has not been saved.', true));
					$dataSource->rollback($this);
				}

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

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

	function edit($id = null) {
		// Check
		$this->_checkCharaSheeAuth();

		$this->_edit($id, false);
	}

	function admin_edit($id = null) {

		$this->_edit($id, true);
	}

	function _edit($id = null, $isAdmin = false) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid CharacterSheet', true));
			$this->redirect(array('action'=>'index'));
		}

		$characterSheet = $this->CharacterSheet->find('first', array(
			'conditions' => array('CharacterSheet.id' => $id),
			'recursive' => -1,
		));
		if (empty($characterSheet)) {
			$this->Session->setFlash(__('Invalid CharacterSheet.', true));
			$this->redirect(array('action'=>'index'));
		}
		// 一般ユーザの場合、自身のキャラシのみ
		if (empty($isAdmin)) {
			$this->__checkCharaSheeOwner($characterSheet);
		}

		if (!empty($this->data)) {
			if ($this->CharacterSheet->save($this->data, array('fieldList' => $this->CharacterSheet->fields['edit']))) {
				$this->Session->setFlash(__('The CharacterSheet has been saved', true));
			} else {
				$this->Session->setFlash(__('The data could not be saved. Please, try again.', true));
			}
		}

		$this->redirect(array('action'=>'view', $id));
	}

	function delete($id = null) {
		// Check
		$this->_checkCharaSheeAuth();

		$this->_delete($id, false);
	}

	function admin_delete($id = null) {

		$this->_delete($id, true);
	}

	function _delete($id = null, $isAdmin = false) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid id for CharacterSheet', true));
			$this->redirect(array('action'=>'index'));
		}

		$characterSheet = $this->CharacterSheet->find('first', array(
			'conditions' => array('CharacterSheet.id' => $id),
			'recursive' => -1,
		));
		if (empty($characterSheet)) {
			$this->Session->setFlash(__('Invalid CharacterSheet.', true));
			$this->redirect(array('action'=>'index'));
		}
		// 一般ユーザの場合、自身のキャラシのみ
		if (empty($isAdmin)) {
			$this->__checkCharaSheeOwner($characterSheet);
		}

		if ($this->CharacterSheet->delete($id)) {
			$dir = $this->getSkinDir($characterSheet['CharacterSheet']['key_name']);

			@unlink($dir. 'view.ctp');
			@unlink($dir. 'admin_view.ctp');
			@rmdir($dir);
			rmdir($this->getSkinDir($characterSheet['CharacterSheet']['key_name'], false));

			$this->Session->setFlash(__('CharacterSheet deleted', true));
			if (!$isAdmin) {
				$this->redirect(array('action'=>'myindex'));
			} else {
				$this->redirect(array('action'=>'index'));
			}
		}

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

	function upload($id = null) {
		// Check
		$this->_checkCharaSheeAuth();

		$this->_upload($id, false);
	}

	function admin_upload($id = null) {

		$this->_upload($id, true);
	}

	function _upload($id = null, $isAdmin = false) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid id for CharacterSheet', true));
			$this->redirect(array('action'=>'index'));
		}

		$characterSheet = $this->CharacterSheet->find('first', array(
			'conditions' => array('CharacterSheet.id' => $id),
			'recursive' => -1,
		));
		if (empty($characterSheet)) {
			$this->Session->setFlash(__('Invalid CharacterSheet.', true));
			$this->redirect(array('action'=>'index'));
		}
		// 一般ユーザの場合、自身のキャラシのみ
		if (empty($isAdmin)) {
			$this->__checkCharaSheeOwner($characterSheet);
		}

		$skin_dir = $this->getSkinDir($characterSheet['CharacterSheet']['key_name']);
		$tmpfile = $skin_dir. 'view.tmp';
		if (!is_dir($skin_dir)) {
			if (!@mkdir($skin_dir, 0777, true)) {
			$this->Session->setFlash(__('Invalid CharacterSheet.', true));
			}
		}

		if (!empty($this->data['CharacterSheet']['file'])) {
			if (empty($this->data['CharacterSheet']['file']['error'])) {
				if (is_uploaded_file($this->data['CharacterSheet']['file']['tmp_name']) && move_uploaded_file($this->data['CharacterSheet']['file']['tmp_name'], $tmpfile)) {
					$upfile = file_get_contents($tmpfile);
					// 文字コード変更
					$encode = mb_detect_encoding($upfile, "UTF-8, sjis-win, sjis, eucjp-win");
					if ($encode != 'UTF-8') {
						$upfile = mb_convert_encoding($upfile, "UTF-8", $encode.", sjis-win, sjis, eucjp-win");
					}
					$encode = mb_detect_encoding($upfile, "UTF-8, sjis-win, sjis, eucjp-win");

					// 一般ユーザの場合:sanitizeTag 
					if (empty($isAdmin)) {
						$Sanitize = CorePlus::set_behavoir('SanitizePlus');
						// sanitize
						$upfile = $Sanitize->stripWhiteTags($upfile);
						// restore
						$upfile = $Sanitize->restoreWhiteTags($upfile, true);
					}

					/* スキン変換 */
					// Character
					$upfile = $this->_charcterData($upfile);

					// Profiles
					// 繰り返し系
					$upfile = $this->_key_name2multiValue($upfile);
					$upfile = $this->_tablekeyname_keyname2tr($upfile);
					// StaticTable
					$upfile = $this->_staticTable_tablekeyname_keyname2value($upfile);
					// key_name単純変換
					$upfile = $this->_key_name2name($upfile);
					$upfile = $this->_key_name2value($upfile);


					// 出力
					$this->_writeSkinFile($skin_dir. 'view.ctp', $upfile);
					$this->_writeSkinFile($skin_dir. 'admin_view.ctp', $upfile);
					@unlink($tmpfile);

					$this->Session->setFlash(__('The new CharacterSheet has been saved.', true));
				} else {
					$this->Session->setFlash(__('The file is invalid.', true));
				}
			} else {
				if ($this->data['CharacterSheet']['file']['error'] == UPLOAD_ERR_NO_FILE) {
					$this->Session->setFlash(__('Please upload.', true));
				} else {
					$this->Session->setFlash(sprintf(__('An error occured while transferring the file (ErrorNo:%s)', true), $this->data['CharacterSheet']['file']['error']));
				}
			}
		}

		$this->redirect(array('action'=>'view', $id));
	}

	function skinsample($system_id = null) {
		$Sanitize = CorePlus::set_behavoir('SanitizePlus');
		$this->set('allow_tags', $Sanitize->usertag_whitelist);

		$this-> _skinsample($system_id, false);
	}

	function admin_skinsample($system_id = null) {
		$this-> _skinsample($system_id, true);
	}

	function _skinsample($system_id = null, $isAdmin = false)
	{
		$this->System = CorePlus::set_model('System');

		if (!empty($system_id)) {
			// 抽出
			$conditions['System.id'] = $system_id;
			$this->System->hasMany['Profile']['fields'] = '';
			$contain = array(
				'Profile' => array(
					'ProfileSelect',
					'ProfileTable' => array(
						'ProfileTableStatic',
					),
				)
			);
			$recursive = 3;

			$system = $this->System->find('first', array(
				'conditions' => $conditions,
				'contain' => $contain,
				'recursive' => $recursive,
			));
			if (!isset($system['System']) || empty($system['System'])) {
				$this->cakeError("error", array('message' => __('No System.', true). ' : system_id = '. $system_id));
			}
			$system = $this->_restore_html_system($system, true);

			if (isset($system['Profile'])) {
				foreach ($system['Profile'] as $k => $v) {
					if (!empty($v)) {
						$system['Profile'][$k] = $this->__restore_html_profile($v);
					}
				}
			}
			$system = $this->HtmlEscape->nl2br_escaped($system);
		} else {
			$system = array();
		}

		$this->set('system', $system);
		$this->set('profile_types', CorePlus::get_profile_types());

		// 出力設定
		// Layout
		$this->layout = 'wrap';

		$this->set('title_for_layout', " - ". __('How to make Skin', true));
	}

	function getSkinDir($dir_name, $isLower = true)
	{
		$skin_dir = APP. 'views'. DS. 'themed'. DS. $dir_name. DS;
		if ($isLower) {
			$skin_dir .= 'characters'. DS;
		}
		return  $skin_dir;
	}

	function _writeSkinFile($file_name, $data)
	{
		$fp = fopen($file_name, "w+");
		@fwrite($fp, $data);
		@fclose($fp);
	}

	/* スキン変換 */
	function __changeSkin($data, $replacement, $pattern, $limit = -1)
	{
		if (empty($data) || empty($pattern)) {
			return $data;
		}

		if (!empty($replacement)) {
			$replacement = '<?php '.$replacement. '; ?>';
		}

		return preg_replace($pattern, $replacement, $data, $limit);
	}

	// Character
	function _charcterData($data)
	{
		$data = $this->__charcterData($data, 'name');
		$data = $this->__charcterData($data, 'notes');
		$data = $this->__charcterData($data, 'modified');
		$data = $this->__charcterData($data, 'userName');

		$data = $this->__charcterData($data, 'mainPicture');
		$data = $this->__charcterData($data, 'fullPicture');

		return $data;
	}
	function __charcterData($data, $key_name)
	{
		switch($key_name) {
			case 'name':
				$pattern = '/{C:name}/';
				$replacement = '\$character[\'Character\'][\'name\']';
				break;
			case 'notes':
				$pattern = '/{C:notes}/';
				$replacement = '\$profiledisp->autoLinkProf(\$character[\'Character\'][\'notes\'])';
				break;
			case 'modified':
				$pattern = '/{C:modified:?(.*)?}/';
				$format = 'Y/m/d H:i';

				if (preg_match($pattern, $data, $matches)) {
					if (!empty($matches[1])) {
						if ($matches[1] == 'short') {
							$replacement = '\$time->niceshort(\$character[\'Character\'][\'modified\'], array(\'format\' => \''. $format. '\'))';
						} else {
							$format = $matches[1];
						}
					}
				}

				if (empty($replacement)) {
					$replacement = '\$time->format("'. $format. '", \$character[\'Character\'][\'modified\'])';
				}

				break;
			case 'userName':
				$pattern = '/{C:userName}/';
				$replacement = '\$character[\'User\'][\'name\']';
				break;


			case 'mainPicture':
			case 'fullPicture':
				if ($key_name == 'mainPicture') {
					$element = 'character_picture_image';
//					$pattern = '/{C:mainPicture:?(.*)?}/';
					$pattern = '/{C:mainPicture([_a-zA-Z0-9:]+)}/';
					$filename = 'main_picture';
				} elseif ($key_name == 'fullPicture') {
					$element = 'character_picture_full';
					$pattern = '/{C:fullPicture([_a-zA-Z0-9:]+)}/';
//					$pattern = '/{C:fullPicture:?(.*)}/';
					$filename = 'full_length';
				} else {
					return $data;
					break;
				}

				$count = preg_match_all($pattern, $data, $matches);
				if (isset($matches[1]) && !empty($matches[1])) {
					foreach ($matches[1] as $v) {
						$arr = explode(":", $v);

						if ($key_name == 'fullPicture') {
							$size = 'fullPicture';
						} else {
							$size = 'l';
						}
						$classname = '';
						$class = '';
						if (isset($arr[1])) {
							$size = $arr[1];
						}
						if (isset($arr[2])) {
							if ($key_name == 'mainPicture') {
								$class = $arr[2];
							} else {
								$classname = $arr[2];
							}
						}

						$replacement = '\$this->element(\''. $element. '\', array(\'basename\' => \$character[\'Character\'][\''. $filename. '\'], \'classname\' => \''.$classname.'\', \'options\' => array(\'previewVersion\' => \''. $size. '\', \'class\' => \''. $class. '\', \'nodata\' => \'image\')));';

					$data = $this->__changeSkin($data, "echo ".$replacement, $pattern, 1);
					}
				}
				return $data;
				break;
			default:
				return $data;
				break;
		}

		return $this->__changeSkin($data, "echo ".$replacement, $pattern);
	}

	// Profiles
	// 単純表示
	function _key_name2value($data)
	{
		$pattern = '/{([_a-z0-9]+)}/';
		$replacement = '\$profiledisp->autoLinkProf(\$characterSheet->profileValue4key_name(\$character["System"]["Profile"], "${1}"))';

		return $this->__changeSkin($data, $replacement, $pattern);
	}
	function _key_name2name($data)
	{
		$pattern = '/{([_a-z0-9]+):title}/';
		$replacement = '\$characterSheet->profileName4key_name(\$character["System"]["Profile"], "${1}")';

		return $this->__changeSkin($data, $replacement, $pattern);
	}

	// StaticTable
	function _staticTable_tablekeyname_keyname2value($data)
	{
		$pattern = '/{ST:([_a-z0-9]+):([_a-z0-9]+):([0-9]+)}/';
		$replacement = '\$characterSheet->staticTable4row_tablekey_name(\$character["System"]["Profile"], "${1}", "${2}", ${3})';

		return $this->__changeSkin($data, $replacement, $pattern);
	}

	// 繰り返し表示
	function _key_name2multiValue($data)
	{
		$pattern = '/{M}(.*){([_a-z0-9]+)}(.*){\/M}/';
		$replacement = '\$characterSheet->multiInput4key_name(\$character["System"]["Profile"], "${2}", \'${1}%s${3}\')';

		return $this->__changeSkin($data, $replacement, $pattern);
	}

	// テーブル
	// 繰り返し表示
	function _tablekeyname_keyname2tr($data)
	{
		$pattern = '/{T:([_a-z0-9]+)}(.*){\/T}/';

		return preg_replace_callback($pattern, array($this, '__tablePattern2key_names'), $data);
	}

	function __tablePattern2key_names($matches)
	{
		$tablekey_name = $matches[1];
		$key_names_parts = $matches[2];

		$pattern = '/{([_0-9a-z]+)}/';

		preg_match_all($pattern, $key_names_parts, $key_matches);
		$keys = $key_matches[1];

		$keys_str = 'array(';
		foreach ($keys as $k => $v) {
			if ($k != 0) {
				$keys_str .= ', ';
			}
			$keys_str .= '"'. $v. '"';
		}
		$keys_str .= ')';

		$replacement = preg_replace($pattern, '%s', $key_names_parts);
		$replacement = '$characterSheet->table4tablekey_name($character["System"]["Profile"], "'.$tablekey_name.'", '. $keys_str. ', \''. $replacement. '\')';
		$replacement = '<?php '.$replacement. '; ?>';

		return $replacement;
	}

	function _checkCharaSheeAuth($system_id = null)
	{
		if (empty($this->site_configs['System.allowUserSheet']['value'])) {
			$this->Session->setFlash(__('Unavailable Now.', true));
			if (!empty($system_id)) {
				$this->redirect(array('controller' => 'systems', 'action'=>'view', $system_id));
			} else {
				$this->redirect(array('controller' => 'systems', 'action'=>'index'));
			}
		}

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

	function __checkCharaSheeOwner($characterSheet)
	{
		if (!$this->_checkCharaSheeOwner($characterSheet)) {
			$this->Session->setFlash(__('No Permission', true));
			$this->redirect(array('action'=>'index'));
		}
	}

	function __getThisSystem($id, $isAdmin = false)
	{
		$this_system = $this->_getThisSystem($id, $isAdmin);

		return $this->__restore_html_system($this_system);
	}

	function __restore_html_system($data)
	{
		if (!isset($data['System']) || empty($data['System'])) {
			return $data;
		}

		return $this->_restore_html_system($data);
	}

}

