<?php
/**
 * Online Players
 * https://webenginecms.org/
 * 
 * @version 1.2.0
 * @author Lautaro Angelico <http://lautaroangelico.com/>
 * @copyright (c) 2013-2020 Lautaro Angelico, All Rights Reserved
 * @build 3d220b662522c313f5980cd685842c3d
 */

namespace Plugin\OnlinePlayers;

class OnlinePlayers {
	
	private $_configXml = 'config.xml';
	private $_modulesPath = 'modules';
	private $_cacheFile = 'online_players.cache';
	private $_cronFile = 'online_players.php';
	
	private $_showClass = true;
	private $_showLevel = true;
	private $_showLastLocation = true;
	private $_showMasterLevel = true;
	private $_combineMasterLevel = true;
	private $_showGuild = true;
	
	private $_usercpmenu = array(
		array(
			'active' => true,
			'type' => 'internal',
			'phrase' => 'onlineplayers_title',
			'link' => 'onlineplayers',
			'icon' => 'usercp_default.png',
			'visibility' => 'user',
			'newtab' => false,
			'order' => 999,
		),
	);
	
	// CONSTRUCTOR
	
	function __construct() {
		
		// load configs
		$this->configFilePath = __PATH_ONLINEPLAYERS_ROOT__.$this->_configXml;
		if(!file_exists($this->configFilePath)) throw new \Exception(lang('onlineplayers_error_5'));
		$xml = simplexml_load_file($this->configFilePath);
		if(!$xml) throw new \Exception(lang('onlineplayers_error_5'));
		
		// set configs	
		$this->_showClass = (int) $xml->show_class;
		$this->_showLevel = (int) $xml->show_level;
		$this->_showLastLocation = (int) $xml->show_location;
		$this->_showMasterLevel = (int) $xml->show_master;
		$this->_combineMasterLevel = (int) $xml->combine_level;
		$this->_showGuild = (int) $xml->show_guild;
		if($this->_combineMasterLevel) {
			$this->_showMasterLevel = true;
		}
		
		// cron
		$this->_checkCron();
	}
	
	// PUBLIC FUNCTIONS
	
	public function loadModule($module) {
		if(!\Validator::Alpha($module)) throw new \Exception(lang('onlineplayers_error_4', true));
		if(!$this->_moduleExists($module)) throw new \Exception(lang('onlineplayers_error_4', true));
		if(!@include_once(__PATH_ONLINEPLAYERS_ROOT__ . $this->_modulesPath . '/' . $module . '.php')) throw new \Exception(lang('onlineplayers_error_4', true));
	}
	
	public function updateCache() {
		
		$onlineCharacters = loadCache('online_characters.cache');
		if(!is_array($onlineCharacters)) {
			$this->_updateCacheFile("");
			return;
		}
		
		$Character = new \Character();
		foreach($onlineCharacters as $characterName) {
			$characterData = $Character->CharacterData($characterName);
			if(!is_array($characterData)) continue;
			
			$playerData = array(
				_CLMN_CHR_NAME_ => $characterData[_CLMN_CHR_NAME_],
				_CLMN_CHR_CLASS_ => $characterData[_CLMN_CHR_CLASS_]
			);
			
			// Level
			if($this->_showLevel) {
				$playerData[_CLMN_CHR_LVL_] = $characterData[_CLMN_CHR_LVL_];
			}
			
			// Map
			if($this->_showLastLocation) {
				$playerData[_CLMN_CHR_MAP_] = $characterData[_CLMN_CHR_MAP_];
			}
			
			// Master Level
			if($this->_showMasterLevel) {
				if(_TBL_MASTERLVL_ == _TBL_CHR_) {
					$playerData[_CLMN_ML_LVL_] = $characterData[_CLMN_ML_LVL_];
				} else {
					$playerMasterLevelData = $Character->getMasterLevelInfo($characterName);
					if(is_array($playerMasterLevelData)) {
						$playerData[_CLMN_ML_LVL_] = $playerMasterLevelData[_CLMN_ML_LVL_];
					}
				}
			}
			
			// Guild
			if($this->_showGuild) {
				$playerGuild = $this->_returnPlayerGuild($characterName);
				$playerData[_CLMN_GUILDMEMB_NAME_] = $playerGuild;
			}
			
			$onlinePlayers[] = $playerData;
		}
		
		$onlinePlayersJson = $this->_prepareCacheData($onlinePlayers);
		if(!check_value($onlinePlayersJson)) {
			$this->_updateCacheFile("");
			return;
		}
		
		$this->_updateCacheFile($onlinePlayersJson);
	}
	
	public function getOnlinePlayersCache() {
		$cacheData = $this->_loadCacheData();
		if(!is_array($cacheData)) return;
		return $cacheData;
	}
	
	public function showClass() {
		return $this->_showClass;
	}
	
	public function showLevel() {
		return $this->_showLevel;
	}
	
	public function showLocation() {
		return $this->_showLastLocation;
	}
	
	public function showMasterLevel() {
		return $this->_showMasterLevel;
	}
	
	public function showGuild() {
		return $this->_showGuild;
	}
	
	public function combineMasterLevel() {
		return $this->_combineMasterLevel;
	}
	
	public function checkPluginUsercpLinks() {
		if(!is_array($this->_usercpmenu)) return;
		$cfg = loadConfig('usercp');
		if(!is_array($cfg)) return;
		foreach($cfg as $usercpMenu) {
			$usercpLinks[] = $usercpMenu['link'];
		}
		foreach($this->_usercpmenu as $pluginMenuLink) {
			if(in_array($pluginMenuLink['link'],$usercpLinks)) continue;
			$cfg[] = $pluginMenuLink;
		}
		usort($cfg, function($a, $b) {
			return $a['order'] - $b['order'];
		});
		$usercpJson = json_encode($cfg, JSON_PRETTY_PRINT);
		$cfgFile = fopen(__PATH_CONFIGS__.'usercp.json', 'w');
		if(!$cfgFile) throw new \Exception('There was a problem opening the usercp file.');
		fwrite($cfgFile, $usercpJson);
		fclose($cfgFile);
	}
	
	// PRIVATE FUNCTIONS
	
	private function _moduleExists($module) {
		if(!check_value($module)) return;
		if(!file_exists(__PATH_ONLINEPLAYERS_ROOT__ . $this->_modulesPath . '/' . $module . '.php')) return;
		return true;
	}
	
	private function _prepareCacheData($data) {
		if(!is_array($data)) return;
		return json_encode($data);
	}
	
	private function _updateCacheFile($data) {
		$file = __PATH_CACHE__.$this->_cacheFile;
		if(!file_exists($file)) return;
		if(!is_writable($file)) return;
		
		$fp = fopen($file, 'w');
		fwrite($fp, $data);
		fclose($fp);
		return true;
	}
	
	private function _loadCacheData() {
		$file = __PATH_CACHE__.$this->_cacheFile;
		if(!file_exists($file)) return;
		
		$cacheData = file_get_contents($file);
		if(!check_value($cacheData)) return;
		
		$cacheDataArray = json_decode($cacheData, true);
		if(!is_array($cacheDataArray)) return;
		
		return $cacheDataArray;
	}
	
	private function _checkCron() {
		$this->db = \Connection::Database('Me_MuOnline');
		$result = $this->db->query_fetch_single("SELECT * FROM ".WEBENGINE_CRON." WHERE cron_file_run = ?", array($this->_cronFile));
		if(is_array($result)) return;
		$this->_createCron();
	}
	
	private function _createCron() {
		$this->db = \Connection::Database('Me_MuOnline');
		if(!file_exists(__PATH_CRON__ . $this->_cronFile)) throw new \Exception(lang('onlineplayers_error_3', true));
		$cronMd5 = md5_file(__PATH_CRON__ . $this->_cronFile);
		if(!check_value($cronMd5)) throw new \Exception(lang('onlineplayers_error_3', true));
		$insertData = array(
			'Online Players',
			$this->_cronFile,
			300,
			1,
			0,
			$cronMd5
		);
		$result = $this->db->query("INSERT INTO ".WEBENGINE_CRON." (cron_name, cron_file_run, cron_run_time, cron_status, cron_protected, cron_file_md5) VALUES (?, ?, ?, ?, ?, ?)", $insertData);
		if(!$result) throw new \Exception(lang('onlineplayers_error_3', true));
	}
	
	private function _returnPlayerGuild($characterName) {
		$db = \Connection::Database('MuOnline');
		$result = $db->query_fetch_single("SELECT * FROM "._TBL_GUILDMEMB_." WHERE "._CLMN_GUILDMEMB_CHAR_." = ?", array($characterName));
		if(!is_array($result)) return;
		if(!check_value($result[_CLMN_GUILDMEMB_NAME_])) return;
		return $result[_CLMN_GUILDMEMB_NAME_];
	}
	
}