<?php
namespace app\controller;

require_once app()->getRootPath() . 'vendor/autoload.php';
use app\BaseController;
use Neoxygen\NeoClient\ClientBuilder;
use think\facade\Request;



class CommonTwoController extends BaseController
{

	// checkIsExistSession
	public function checkIslogin()
	{
		return Request::session('name') ?? false;
	}

	/**
	 * Xy
	 * Connect Neo4j
	 * return Object
	 */
	private  function connectNeo4j()
	{
		$client = ClientBuilder::create()
			->addConnection('default', 'http', '124.70.100.133', 7474, true, 'neo4j', 'neo4j-pwd')
			->setAutoFormatResponse(true)
			->setDefaultTimeout(200)
			->build();
		return $client;
	}

	/**
	 * Zy
	 * Connect Neo4j
	 * return Object
	 */
	private  function connectNeo4jByzy()
	{
		$client = ClientBuilder::create()
			->addConnection('default', 'http', '120.46.136.62', 7474, true, 'neo4j', 'neo4j-pwd')
			->setAutoFormatResponse(true)
			->setDefaultTimeout(200)
			->build();
		return $client;
	}

	/**
	 * Document|Guide
     * Connect Neo4j
     * return Object
     */

    private  function connectNeo4jByDocgui()
    {
        $client = ClientBuilder::create()
            ->addConnection('default', 'http', '121.36.94.218', 7474, true, 'neo4j', 'neo4j-pwd')
            ->setAutoFormatResponse(true)
            ->setDefaultTimeout(200)
            ->build();
        return $client;
    }

    /**
     * 获取neo4j连接
     */
    public function getNeo4jConnect($tag)
    {
        if('zy' === $tag) {
            $client = $this->connectNeo4jByzy();
        } elseif('xy' === $tag) {
            $client = $this->connectNeo4j();
        } elseif('guide' === $tag){
            $client = $this->connectNeo4jByDocgui();
        }
        return $client;
    }




    /**
     * Select SingleNode
     * @param $node  string
     * @param $label string
     * @param $field string
     * @param $value string
     * return array
     */
    public  function getNodes($tag , $node , $label , $skip , $limit , $field = '' , $value = '' , $fields = [])
    {
        $client = $this->getNeo4jConnect($tag);

        if($field) {
            $query  = "match (". $node . ":" . $label .")"."where $node . $field =~ '.*".$value.".*' ". " RETURN $node";
            $data   = $client->sendCypherQuery($query)->getResult();
        } else {
            $query  = "match (". $node . ":" . $label .") RETURN $node skip $skip limit $limit";
            $data   = $client->sendCypherQuery($query)->getResult();
        }

        foreach ($data->getNodes() as $key => $node){
            $datas[] = ['id' => $node->getId()];
        }

        $list   = array_column($p = $data->getTableFormat() , 'n');
        foreach ($list as $k => $value) {
            $list[$k]['id'] = $datas[$k]['id'];
        }

        $query1 = "MATCH (n:".$label.") RETURN count(n) as count";
        $count  = $client->sendCypherQuery($query1)->getResult()->getTableFormat();
        $list   = ['list' => $list , 'count' => $count[0]['count']];
        return $list;
    }



    /**
     * ID获取节点
     */
    public function getNodeById($zsk , $id , $tag = '')
    {
        $client = $this->getNeo4jConnect($zsk);
        $query  = "MATCH (n) WHERE id(n)=$id RETURN n";
        $result = $client->sendCypherQuery($query)->getResult()->getSingleNode();
        if($tag) {
            return $result->getLabels();
        }
        $detail = $result->getProperties();
        $detail['id'] = $id;
        return $detail;
    }


    /**
     * 节点属性修改
     */
    public function setNode($query , $tag = 'zy')
    {
        $client = $this->getNeo4jConnect($tag);
        $result = $client->sendCypherQuery($query);
        return $result;
    }


    /**
     * Create Node
     * @param $node  string
     * @param $label string
     * @param $data  array
     */
    public  function createNode($node , $label , $data)
    {
        $client = $this->getNeo4jConnect('guide');
        $str		= json_encode($data , JSON_UNESCAPED_UNICODE);
        $singleData = preg_replace('/"([a-zA-Z]+[a-zA-Z0-9]*)":/' ,'$1:' , $str); 	 // 替换key引号
        $query  	= "CREATE (". $node . ":" . $label . $singleData . ") RETURN $node";
        $query      = stripslashes($query);
        return $client->sendCypherQuery($query);
    }



    // ----------------------------------------------------------

    // 获取文献|指南属性
    public function getProperty($query)
    {
        $client = $this->connectNeo4jByDocgui();
        $data   = $client->sendCypherQuery($query)->getResult();
        return $data->getTableFormat();
    }


    // 获取文献总条数
    public function _getTotalCount($query)
    {
        $client = $this->connectNeo4jByDocgui();
        $result = $client->sendCypherQuery($query)->getResult();
        $count  = $result->getTableFormat();
        return $count[0]['count'] ?? 0;
    }


    // 获取文献属性id
    public function _getId($val , $tag = 'hot')
    {
        $client   = $this->connectNeo4jByDocgui();
        $query1   = "match(n:Keyword {name:"."'".$val."'"."}) return n";
        $query2   = "match(n:Author {kgid:"."'".$val."'"."}) return n";
        $query    = $tag == 'hot' ? $query1 : $query2;
        return $client->sendCypherQuery($query)->getResult()->getSingleNode()->getId();
    }


	// 获取标签属性
	public function getAboutInfo($query , $tag = '')
	{
		$client = $tag ? $this->connectNeo4jByzy() : $this->connectNeo4j();
		$data   = $client->sendCypherQuery($query)->getResult();
		return $data->getTableFormat();
	}


	// 获取总条数
	public function getTotalCount($query , $tag = '')
	{
		$client = $tag ? $this->connectNeo4jByzy() : $this->connectNeo4j();
		$result = $client->sendCypherQuery($query)->getResult();
		$count  = $result->getTableFormat();
		return $count[0]['count'] ?? 0;
	}


	// 获取属性id
	public function getId($val , $tag = 'hot')
	{
		$client   = $this->connectNeo4j();
        $query1   = "match(n:Keyword {name:"."'".$val."'"."}) return n";
        $query2   = "match(n:Author {kgid:"."'".$val."'"."}) return n";
		$query    = $tag == 'hot' ? $query1 : $query2;
		return $client->sendCypherQuery($query)->getResult()->getSingleNode()->getId();
	}


	public function getXyR($query , $query1  = '', $query2 = '')
	{
		$client   = $this->connectNeo4j();
		$result   = $client->sendCypherQuery($query)->getResult();

		foreach ($result->getRelationships() as $rel)
		{
			$edges[] = [
				'start' => [
					'identity'	   	=> $rel->getStartNode()->getId() ,
					'labels'		=> $rel->getStartNode()->getLabels(),
					'properties'   	=> $rel->getStartNode()->getProperties(),
				] ,
				'end' => [
					'identity'	   	=> $rel->getEndNode()->getId() ,
					'labels'		=> $rel->getEndNode()->getLabels(),
					'properties'   	=> $rel->getEndNode()->getProperties(),
				],
				'relationship'	=> [
					'start'			=>  $rel->getStartNode()->getId() ,
					'end'			=>  $rel->getEndNode()->getId() ,
					'type'			=>  $rel->getType(),
					'properties' 	=> $rel->getProperties()

				]
			];
		}

		if($query1) {
			$result1   = $client->sendCypherQuery($query1)->getResult();
			foreach ($result1->getRelationships() as $rel1)
			{
				$edges1[] = [
					'start' => [
						'identity'	   	=> $rel1->getStartNode()->getId() ,
						'labels'		=> $rel1->getStartNode()->getLabels(),
						'properties'   	=> $rel1->getStartNode()->getProperties(),
					] ,
					'end' => [
						'identity'	   	=> $rel1->getEndNode()->getId() ,
						'labels'		=> $rel1->getEndNode()->getLabels(),
						'properties'   	=> $rel1->getEndNode()->getProperties(),
					],
					'relationship'	=> [
						'start'			=>  $rel1->getStartNode()->getId() ,
						'end'			=>  $rel1->getEndNode()->getId() ,
						'type'			=>  $rel1->getType(),
						'properties' 	=> 	$rel1->getProperties()

					]
				];
			}
		}


		if($query2) {
			$result2   = $client->sendCypherQuery($query2)->getResult();
			foreach ($result2->getRelationships() as $rel2)
			{
				$edges2[] = [
					'start' => [
						'identity'	   	=> $rel2->getStartNode()->getId() ,
						'labels'		=> $rel2->getStartNode()->getLabels(),
						'properties'   	=> $rel2->getStartNode()->getProperties(),
					] ,
					'end' => [
						'identity'	   	=> $rel2->getEndNode()->getId() ,
						'labels'		=> $rel2->getEndNode()->getLabels(),
						'properties'   	=> $rel2->getEndNode()->getProperties(),
					],
					'relationship'	=> [
						'start'			=>  $rel2->getStartNode()->getId() ,
						'end'			=>  $rel2->getEndNode()->getId() ,
						'type'			=>  $rel2->getType(),
						'properties' 	=> 	$rel2->getProperties()
					]
				];
			}
		}

		$edges  = $edges  ?? [];
		$edges1 = $edges1 ?? [];
		$edges2 = $edges2 ?? [];

		return array_merge($edges , $edges1 , $edges2);
	}


	public function getZyR($query , $query1 , $query2 , $query3)
	{
		if($query && $query1 && $query2 && $query3) {
			$r1 = $this->getRelationship($query);
			$r2 = $this->getRelationship($query1);
			$r3 = $this->getRelationship($query2);
			$r4 = $this->getRelationship($query3);
			return array_merge($r1 , $r2 , $r3 , $r4);
		} elseif ($query && !$query1 && !$query2 && !$query3) {
			$r = $this->getRelationship($query);
			return $r;
		}
	}


	public function getSingle($query , $tag = '')
	{
		$client 	= $tag ? $this->connectNeo4jByzy() : $this->connectNeo4j();
		$result   	= $client->sendCypherQuery($query)->getResult()->getSingleNode();
		$results[]  = [
			'start' => [
				'identity'	   	=> $result->getId() ,
				'labels'		=> $result->getLabels(),
				'properties'   	=> $result->getProperties(),
			]
		];
		return $results;
	}


	public function getRelationship($query , $tag = '')
	{
		$client   = $tag ? $this->connectNeo4j() : $this->connectNeo4jByzy();
		$result   = $client->sendCypherQuery($query)->getResult();
		foreach ($result->getRelationships() as $rel)
		{
			$results[] = [
				'start' => [
					'identity'	   	=> $rel->getStartNode()->getId() ,
					'labels'		=> $rel->getStartNode()->getLabels(),
					'properties'   	=> $rel->getStartNode()->getProperties(),
				] ,
				'end' => [
					'identity'	   	=> $rel->getEndNode()->getId() ,
					'labels'		=> $rel->getEndNode()->getLabels(),
					'properties'   	=> $rel->getEndNode()->getProperties(),
				],
				'relationship'	=> [
					'start'			=>  $rel->getStartNode()->getId() ,
					'end'			=>  $rel->getEndNode()->getId() ,
					'type'			=>  $rel->getType(),
					'properties' 	=>  $rel->getProperties()

				]
			];
		}
		$results = $results ?? [];
		return $results;
	}


	public function getComplication($query , $tag = '')
	{
		$client   = $tag ? $this->connectNeo4jByzy() : $this->connectNeo4j();
		$result   = $client->sendCypherQuery($query)->getResult();
		foreach ($result->getRelationships() as $rel) {
			$results[] = [
				'properties'=> $rel->getEndNode()->getProperty('name')
			];
		}
		return $results ?? [];
	}


	public function checkPhone($phone)
	{
		return preg_match("/^1[3456789]{1}\d{9}$/", $phone) ?? false;
	}

	public function _json_succ($data = [] , $code = 0 , $msg = 'Success')
	{
		return json(['code' => $code , 'msg' => $msg , 'data' => $data]);
	}

	public function _json_error($msg = '' , $code = 1 , $data = null)
	{
		return json(['code' => $code , 'msg' => $msg , 'data' => $data]);
	}



    /**
     * 格式化text文案
     * @param array $data
     * @return array
     */
    public static function beautifyText($data) {
        $searchStr = [
            ' 1.',' 2.',' 3.',' 4.',
            '(1)','(2)','(3)','(4)',
            '0级','Ⅰ级','Ⅱ级','Ⅲ级','Ⅳ级',
            //'①','②','③','④','⑤','⑥','⑦',
            '•',
            '一、','二、','三、','四、',
            '(一)','(二)','(三)','(四)'
        ];
        $replaceStr = [
            "\r\n1.","\r\n2.","\r\n3.","\r\n4.",
            "\r\n\t(1)","\r\n\t(2)","\r\n\t(3)","\r\n\t(4)",
            "\r\n\t0级","\r\n\tⅠ级","\r\n\tⅡ级","\r\n\tⅢ级","\r\n\tⅢ级","\r\n\tⅣ级",
            "\r\n\t①","\r\n\t②","\r\n\t③","\r\n\t④","\r\n\t⑤","\r\n\t⑥","\r\n\t⑦",
            "\r\n\t•",
            "\r\n\t\t一、","\r\n\t\t二、","\r\n\t\t三、","\r\n\t\t四、",
            "\r\n\t\t\t(一)","\r\n\t\t\t(二)","\r\n\t\t\t(三)","\r\n\t\t\t(四)",
        ];
        if(is_array($data)) {
            foreach ($data as &$item){
                $item['text'] = str_replace($searchStr,$replaceStr,$item['text']);
            }
            return $data;
        }
        return str_replace($searchStr,$replaceStr,$data);
    }


    /**加密 解密 时间限制
     * @param $string
     * @param string $operation
     * @param string $key
     * @param int $expiry
     * @return false|string
     */
    //print_r(self::encrypteAndDecrypt('123456','E','app',60));
    //var_dump(self::encrypteAndDecrypt('4defT76Ez1PcSvG6qCLyKSkjGlIIxkhzplV4JfMpvn_hqb4','D','app'));
    public function encrypteAndDecrypt(string $string,string $operation = 'D',string $key = '',int $expiry = 0)
    {
        // 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
        $ckey_length = 4;

        // 密匙
        $key = md5($key ? MD5($key) : MD5('QeEMcyiwg'));

        // 密匙a会参与加解密
        $keya = md5(substr($key, 0, 16));
        // 密匙b会用来做数据完整性验证
        $keyb = md5(substr($key, 16, 16));

        $string = strtr($string, '-_', '+/=');

        // 密匙c��于变化生成的密文
        $keyc = $ckey_length ? ($operation == 'D' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
        // 参与运算的密匙
        $cryptkey = $keya . md5($keya . $keyc);
        $key_length = strlen($cryptkey);
        // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性
        // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
        $string = $operation == 'D' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
        $string_length = strlen($string);
        $result = '';
        $JinMi = range(0, 255);
        $rndkey = array();
        // 产生密匙簿
        for ($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }
        // 用固定的算法，打乱密匙簿，增加随机性
        for ($j = $i = 0; $i < 256; $i++) {
            $j = ($j + $JinMi[$i] + $rndkey[$i]) % 256;
            $tmp = $JinMi[$i];
            $JinMi[$i] = $JinMi[$j];
            $JinMi[$j] = $tmp;
        }
        // 核心加解密部分
        for ($a = $j = $i = 0; $i < $string_length; $i++) {
            $a = ($a + 1) % 256;
            $j = ($j + $JinMi[$a]) % 256;
            $tmp = $JinMi[$a];
            $JinMi[$a] = $JinMi[$j];
            $JinMi[$j] = $tmp;
            // 从密匙簿得出密匙进行异或，再转成字符
            $result .= chr(ord($string[$i]) ^ ($JinMi[($JinMi[$a] + $JinMi[$j]) % 256]));
        }
        if ($operation === 'D') {
            // 验证数据有效性，请看未加密明文的格式
            if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
            // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
            $result = $keyc . str_replace('=', '', base64_encode($result));
            $result = strtr($result, '+/=', '-_');

            return $result;
        }
    }


    /**
     * 获取字符首字母
     */
    public function getFirstCharters($str)
    {
        $str = substr($str , 0 , 3);
        $s1 = iconv('UTF-8', 'gb2312//IGNORE', $str);
        if(empty($s1)) {
            return null;
        }

        $s2 = iconv('gb2312', 'UTF-8', $s1);
        if(empty($s2)) {
            return null;
        }

        $s = $s2 == $str ? $s1 : $str;
        $asc = ord($s{0}) * 256 + ord($s{1}) - 65536;
        if ($asc >= -20319 && $asc <= -20284)
            return 'A';
        if ($asc >= -20283 && $asc <= -19776)
            return 'B';
        if ($asc >= -19775 && $asc <= -19219)
            return 'C';
        if ($asc >= -19218 && $asc <= -18711)
            return 'D';
        if ($asc >= -18710 && $asc <= -18527)
            return 'E';
        if ($asc >= -18526 && $asc <= -18240)
            return 'F';
        if ($asc >= -18239 && $asc <= -17923)
            return 'G';
        if ($asc >= -17922 && $asc <= -17418)
            return 'H';
        if ($asc >= -17417 && $asc <= -16475)
            return 'J';
        if ($asc >= -16474 && $asc <= -16213)
            return 'K';
        if ($asc >= -16212 && $asc <= -15641)
            return 'L';
        if ($asc >= -15640 && $asc <= -15166)
            return 'M';
        if ($asc >= -15165 && $asc <= -14923)
            return 'N';
        if ($asc >= -14922 && $asc <= -14915)
            return 'O';
        if ($asc >= -14914 && $asc <= -14631)
            return 'P';
        if ($asc >= -14630 && $asc <= -14150)
            return 'Q';
        if ($asc >= -14149 && $asc <= -14091)
            return 'R';
        if ($asc >= -14090 && $asc <= -13319)
            return 'S';
        if ($asc >= -13318 && $asc <= -12839)
            return 'T';
        if ($asc >= -12838 && $asc <= -12557)
            return 'W';
        if ($asc >= -12556 && $asc <= -11848)
            return 'X';
        if ($asc >= -11847 && $asc <= -11056)
            return 'Y';
        if ($asc >= -11055 && $asc <= -10247)
            return 'Z';
        return $this->rare_words($asc);
    }


    public function rare_words($asc='')
    {
        $rare_arr = array(
            -3652=>array('word'=>"窦",'first_char'=>'D'),
            -8503=>array('word'=>"奚",'first_char'=>'X'),
            -9286=>array('word'=>"酆",'first_char'=>'F'),
            -7761=>array('word'=>"岑",'first_char'=>'C'),
            -5128=>array('word'=>"滕",'first_char'=>'T'),
            -9479=>array('word'=>"邬",'first_char'=>'W'),
            -5456=>array('word'=>"臧",'first_char'=>'Z'),
            -7223=>array('word'=>"闵",'first_char'=>'M'),
            -2877=>array('word'=>"裘",'first_char'=>'Q'),
            -6191=>array('word'=>"缪",'first_char'=>'M'),
            -5414=>array('word'=>"贲",'first_char'=>'B'),
            -4102=>array('word'=>"嵇",'first_char'=>'J'),
            -8969=>array('word'=>"荀",'first_char'=>'X'),
            -4938=>array('word'=>"於",'first_char'=>'Y'),
            -9017=>array('word'=>"芮",'first_char'=>'R'),
            -2848=>array('word'=>"羿",'first_char'=>'Y'),
            -9477=>array('word'=>"邴",'first_char'=>'B'),
            -9485=>array('word'=>"隗",'first_char'=>'K'),
            -6731=>array('word'=>"宓",'first_char'=>'M'),
            -9299=>array('word'=>"郗",'first_char'=>'X'),
            -5905=>array('word'=>"栾",'first_char'=>'L'),
            -4393=>array('word'=>"钭",'first_char'=>'T'),
            -9300=>array('word'=>"郜",'first_char'=>'G'),
            -8706=>array('word'=>"蔺",'first_char'=>'L'),
            -3613=>array('word'=>"胥",'first_char'=>'X'),
            -8777=>array('word'=>"莘",'first_char'=>'S'),
            -6708=>array('word'=>"逄",'first_char'=>'P'),
            -9302=>array('word'=>"郦",'first_char'=>'L'),
            -5965=>array('word'=>"璩",'first_char'=>'Q'),
            -6745=>array('word'=>"濮",'first_char'=>'P'),
            -4888=>array('word'=>"扈",'first_char'=>'H'),
            -9309=>array('word'=>"郏",'first_char'=>'J'),
            -5428=>array('word'=>"晏",'first_char'=>'Y'),
            -2849=>array('word'=>"暨",'first_char'=>'J'),
            -7206=>array('word'=>"阙",'first_char'=>'Q'),
            -4945=>array('word'=>"殳",'first_char'=>'S'),
            -9753=>array('word'=>"夔",'first_char'=>'K'),
            -10041=>array('word'=>"厍",'first_char'=>'S'),
            -5429=>array('word'=>"晁",'first_char'=>'C'),
            -2396=>array('word'=>"訾",'first_char'=>'Z'),
            -7205=>array('word'=>"阚",'first_char'=>'K'),
            -10049=>array('word'=>"乜",'first_char'=>'N'),
            -10015=>array('word'=>"蒯",'first_char'=>'K'),
            -3133=>array('word'=>"竺",'first_char'=>'Z'),
            -6698=>array('word'=>"逯",'first_char'=>'L'),
            -9799=>array('word'=>"俟",'first_char'=>'Q'),
            -6749=>array('word'=>"澹",'first_char'=>'T'),
            -7220=>array('word'=>"闾",'first_char'=>'L'),
            -10047=>array('word'=>"亓",'first_char'=>'Q'),
            -10005=>array('word'=>"仉",'first_char'=>'Z'),
            -3417=>array('word'=>"颛",'first_char'=>'Z'),
            -6431=>array('word'=>"驷",'first_char'=>'S'),
            -7226=>array('word'=>"闫",'first_char'=>'Y'),
            -9293=>array('word'=>"鄢",'first_char'=>'Y'),
            -6205=>array('word'=>"缑",'first_char'=>'G'),
            -9764=>array('word'=>"佘",'first_char'=>'S'),
            -9818=>array('word'=>"佴",'first_char'=>'N'),
            -9509=>array('word'=>"谯",'first_char'=>'Q'),
            -3122=>array('word'=>"笪",'first_char'=>'D'),
            -9823=>array('word'=>"佟",'first_char'=>'T'),
        );
        if(array_key_exists($asc, $rare_arr) && $rare_arr[$asc]['first_char']){
            return $rare_arr[$asc]['first_char'] ;
        }else{
            return null;
        }
    }

    /**
     *  Curl request
     */
    public function curlRequest($url , $method = 'GET' , $post_data = '')
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        if('POST' === $method) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);     // 设置post方式提交，使用get方式也可开启此项
        }
        curl_setopt($curl, CURLOPT_HEADER, 0);                // 设置http头部信息不输出
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);        // 设置获取的信息以文件流的形式返回，而不是直接输出。
        $result = curl_exec($curl);
        curl_close($curl);
        return $result;
    }

    /**
     * 调试输出
     * @param string $message
     * @param mixed $data
     */
    protected function debug($message, $data = null)
    {
        if (env('APP_DEBUG')) {
            trace($message . ': ' . json_encode($data, JSON_UNESCAPED_UNICODE));
        }
    }

}
