<?php

class Andy_SimilarThreads_ControllerPublic_Forum extends XFCP_Andy_SimilarThreads_ControllerPublic_Forum
{
    public function actionCreateThread()
    {
		//########################################
		// Create loadJavaScript variable and
		// add to params.
		//########################################
		
        // get parent     
        $parent = parent::actionCreateThread();
		
		// check for user group permission
		if (!XenForo_Visitor::getInstance()->hasPermission('similarThreadsGroupID', 'similarThreadsID'))
		{
			return $parent;
		}
		
        // get options from Admin CP -> Options -> Similar Threads -> Show Create Thread
        $showCreateThread = XenForo_Application::get('options')->similarThreadsShowCreateThread;				
		
		// declare variable
		$loadJavaScript = '';
		
		// run if showCreateThread
		if ($showCreateThread)
		{
			// get nodeId       
			$forumId = $this->_input->filterSingle('node_id', XenForo_Input::UINT);
			$forumName = $this->_input->filterSingle('node_name', XenForo_Input::STRING);
			$ftpHelper = $this->getHelper('ForumThreadPost');
			$forum = $ftpHelper->assertForumValidAndViewable($forumId ? $forumId : $forumName);
			$nodeId = $forum['node_id'];       
	   
			// get options from Admin CP -> Options -> Similar Threads -> Exclude Forums  
			$excludeForums = XenForo_Application::get('options')->similarThreadsExcludeForums;
	   
			$excludeForumsArray = explode(',', $excludeForums);  
			  
			// check for excluded forums
			if (!in_array($nodeId, $excludeForumsArray))
			{
				// showCreateThread is enabled and forum is not excluded
				$loadJavaScript = true;
			   
				// prepare viewParams
				if ($parent instanceOf XenForo_ControllerResponse_View)
				{
					// prepare viewParams
					$viewParams = array(
						'loadJavaScript' => $loadJavaScript
					);
				   
					// add viewParams to parent params
					$parent->params += $viewParams;
				}
			}
		}
      
        // return parent
        return $parent;
	}
	
    public function actionSimilarThreads()
    {
		//########################################
		// Show similar threads when member is
		// creating a new thread.
		//########################################
		
		// declare variables
		$currentNodeId = '';
		$currentThreadId = '';
		$similarThreads = array();
		$searchWords = array();
		$searchWord1 = '';
		$searchWord2 = '';
		$threadIds = array();
		
		// get nodeId
		$currentNodeId = $this->_input->filterSingle('node_id', XenForo_Input::UINT);
		
		// get userId
		$visitor = XenForo_Visitor::getInstance();
        $userId = $visitor['user_id'];		
		
		//########################################
		// "View threads by others" permission
		//########################################		
		
		$forumId = $currentNodeId;
		$nodePermissions = $visitor->getNodePermissions($forumId);
		$viewOthers = XenForo_Permission::hasContentPermission($nodePermissions, 'viewOthers');
		
		//########################################
		// search type
		//########################################
		
		// get options from Admin CP -> Options -> Similar Threads -> Enhanced Search  
		$enhancedSearch = XenForo_Application::get('options')->similarThreadsEnhancedSearch;	

		//########################################
		// enhanced search
		//########################################							
			
		// if enhanced search
		if ($enhancedSearch)
		{
			// get thread title
			$threadTitle = $this->_input->filterSingle('title', XenForo_Input::STRING);	
			
			// replace double quote
			$threadTitle = str_replace('"', "", $threadTitle);
			
			// replace backslash
			$threadTitle = str_replace('\\', "", $threadTitle);
			
			// replace tab
			$threadTitle = str_replace('	', " ", $threadTitle);									
			
			// get options from Admin CP -> Options -> Similar Threads -> Maximum Results  
			$maximumResults = XenForo_Application::get('options')->similarThreadsMaximumResults;			
			
			// get options from Admin CP -> Options -> Similar Threads -> Exclude Forums  
			$excludeForums = XenForo_Application::get('options')->similarThreadsExcludeForums;				
			
			// get options from Admin CP -> Options -> Similar Threads -> Same Forum  
			$sameForum = XenForo_Application::get('options')->similarThreadsSameForum;									

			// get ElasticSearch options	
			$esServerOption = XenForo_Application::get('options')->elasticSearchServer;
			
			// get ElasticSearch host	
			$esHost = $esServerOption['host'];			
			
			// get ElasticSearch port number
			$esPort = $esServerOption['port'];
			
			// get ElasticSearch index name
			$indexName = XenES_Api::getInstance()->getIndex();								

			//########################################
			// viewable nodes
			//########################################
			
			// define variable;
			$whereclause1 = '';			
						
			// get viewableNodes
			$viewableNodes = $this->getModelFromCache('XenForo_Model_Node')->getViewableNodeList();
			
			if ($viewableNodes)
			{
				// get nodeIds
				foreach ($viewableNodes as $node)
				{
					$nodeIds[] = $node['node_id'];
				}
			
				// create whereclause
				$whereclause1 = '"' . implode('", "', $nodeIds);
				$whereclause1 = $whereclause1 . '"';
			}
			
			//########################################
			// exclude forums
			//########################################
			
			// define variables;
			unset($nodeIds);
			$whereclause2 = '';			
			
			if ($excludeForums != '')
			{
				// remove trailing comma
				$excludeForumsArray = rtrim($excludeForums, ',');				
				
				$nodeIds = explode(',', $excludeForumsArray);		
				
				// create whereclause
				$whereclause2 = '"' . implode('", "', $nodeIds);
				$whereclause2 = $whereclause2 . '"';
			}			

			// results for all forums
			if ($sameForum == 0)
			{
				// define data_string
				$data_string = '{
					"from" : 0, "size" : "' . $maximumResults . '",
					"query": {
						"filtered": {
							"query": {
								"match" : {
									"thread.title" : {
										"query" : "' . $threadTitle . '",
										"operator": "or"
									}
								}
							},
							"filter": {
								"bool" : {
									"must" : [
										{
											"terms" : {"thread.node" : [' . $whereclause1 . ']}
										}
									],
									"must_not" : [ 
										{ 
											"terms" : {"thread.node" : [' . $whereclause2 . ']}
										}										
									],
									"should" : []
								}
							}
						}
					}
				}';
			}			

			// results for current forums
			if ($sameForum == 1 AND $viewOthers == 1)
			{
				// define data_string
				$data_string = '{
					"from" : 0, "size" : "' . $maximumResults . '",
					"query": {
						"filtered": {
							"query": {
								"match" : {
									"thread.title" : {
										"query" : "' . $threadTitle . '",
										"operator": "or"
									}
								}
							},
							"filter": {
								"bool" : {
									"must" : {
										"term": {
											"thread.node" : "' . $currentNodeId . '"
										}
									}
								}
							}
						}
					}
				}';
			}
			
			// results for current forums
			if ($sameForum == 1 AND $viewOthers == '')
			{
				// define data_string
				$data_string = '{
					"from" : 0, "size" : "' . $maximumResults . '",
					"query": {
						"filtered": {
							"query": {
								"match" : {
									"thread.title" : {
										"query" : "' . $threadTitle . '",
										"operator": "or"
									}
								}
							},
							"filter": {
								"bool" : {
									"must" : {
										"term": {
											"thread.node" : "' . $currentNodeId . '",
											"thread.user" : "' . $userId . '"
										}
									}
								}
							}
						}
					}
				}';
			}		
			
			$ch = curl_init($esHost . ':' . $esPort . '/' . $indexName . '/_search?pretty=true');
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
			
			curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                                                          
			'Content-Type: application/json',                                                                                
			'Content-Length: ' . strlen($data_string))                                                                       
			); 
			 
			curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string );
			curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
			
			$results = curl_exec($ch);			
			
			// parse json results
			$data = json_decode($results);
			
			// get threadIds
			foreach ($data->hits->hits as $var) {
				$threadIds[] = $var->_id;
			}

			// run query if we have a threadIds
			if ($threadIds)
			{
				// run query in model    
				$similarThreads = $this->getModelFromCache('Andy_SimilarThreads_Model')->getThreadsEnhancedSearch($threadIds);
			}
		}
		
		//########################################
		// standard search
		//########################################				
	
		// if not enhanced search
		if (!$enhancedSearch)
		{
			// get threadTitle
			$threadTitle = $this->_input->filterSingle('title', XenForo_Input::STRING);
			
			// get options from Admin CP -> Options -> Similar Threads -> Remove Punctuations
			$removePunctuations = XenForo_Application::get('options')->removePunctuations;
			
			// put into array
			$removePunctuationsArray = explode(' ', $removePunctuations);				
			
			// remove punctuations			
			$threadTitle = str_replace($removePunctuationsArray, '', $threadTitle);	
			
			// get options from Admin CP -> Options -> Similar Threads -> Multibyte
			$multibyte = XenForo_Application::get('options')->similarThreadsMultibyte;		
	
			if ($multibyte == 0)
			{
				// put into array
				$threadTitleArray = explode(' ', $threadTitle);
			}
	
			if ($multibyte == 1)
			{
				// put into array
				$threadTitleArray = mb_split(' ', $threadTitle);
			}
			
			// get options from Admin CP -> Options -> Similar Threads -> Common Words    
			$commonWords = XenForo_Application::get('options')->similarThreadsCommonWords;
			
			// create commonWordsArray
			$commonWordsArray = explode(' ', $commonWords);
			
			// get options from Admin CP -> Options -> Similar Threads -> Miniumum Common Word Length    
			$minimumCommonWordLength = XenForo_Application::get('options')->similarThreadsMinimumCommonWordLength;						
			
			// remove any common words from array
			foreach ($threadTitleArray as $var)
			{
				if ($multibyte == 0)
				{
					if (!in_array(strtolower($var), $commonWordsArray))
					{					
						if (strlen($var) >= $minimumCommonWordLength)
						{
							$searchWords[] = $var;
						}
					}
				}
	
				if ($multibyte == 1)
				{			
					if (!in_array(mb_strtolower($var), $commonWordsArray))
					{					
						if (mb_strlen($var) >= $minimumCommonWordLength)
						{
							$searchWords[] = $var;
						}
					}
				}
			}
			
			$count = count($searchWords);
			
			// only continue if we have a search word
			if ($count > 0)
			{				
				// get first search word
				$searchWord1 = $searchWords[0];
				
				if ($count > 1)
				{	
					// get second search word
					$searchWord2 = $searchWords[1];	
				}			
			}
			
			// run query only if we have a search
			if ($searchWord1 != '')
			{
				// run query in model    
				$similarThreads = $this->getModelFromCache('Andy_SimilarThreads_Model')->getThreads($searchWord1,$searchWord2,$currentNodeId,$currentThreadId,$viewOthers);    
			} 
		}
		
		//########################################
		// prepare viewParams
		//########################################
		
		// declare variables
		$similarThreadsNew = array();
		$i = 0;
		
		// add to multidimensional array
		foreach ($similarThreads as $k => $v)
		{ 
			// prepare array
			$forumArray = array('forum' => array(
				'node_id' => $v['node_id'],
				'title' => $v['nodeTitle']
			));	
			
			// prepare array
			$lastPostInfoArray = array('lastPostInfo' => array(
				'user_id' => $v['last_post_user_id'],
				'username' => $v['last_post_username']
			));	
			
			// prepare array
			$hasPreviewArray = array('hasPreview' => true);			
			
			// merge arrays
			$similarThreadsNew[] = array_merge($similarThreads[$i], $forumArray, $lastPostInfoArray, $hasPreviewArray);				
			
			$i = $i + 1;	
		}
		
		// rename variable
		$similarThreads = $similarThreadsNew;				
		
		// prepare viewParams for template
		$viewParams = array(
			'similarThreads' => $similarThreads
		);
		
		// send to template
		return $this->responseView('Andy_SimilarThreads_ViewPublic_SimilarThreads', 'andy_similarthreads_create_thread', $viewParams);
	}
}