<?php
namespace Elastics;

use  Elasticsearch\ClientBuilder;
use Error\CodeConfigModel;
use Error\ErrorModel;
use Our\ApiConst;
use Our\NameConst;

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/8/17
 * Time: 15:11
 */
class ElasticsToolModel
{
    protected $dbName;
    protected $tbName;
    protected $client;

    protected function __construct($dbName, $tbName)
    {
        $elasticConfig = \Our\Common::getConfig(NameConst::elasticName);
        $configArray = array(
            'host' => $elasticConfig->host,
            'port' => $elasticConfig->port,
            'scheme' => $elasticConfig->scheme
        );
        try {
            $this->dbName = $dbName;
            $this->tbName = $tbName;
            $this->client = ClientBuilder::create()->setHosts($configArray)->build();
        } catch (\Exception $e) {
            ErrorModel::throwException(CodeConfigModel::elasticsError);
        }
    }

    protected function initParams()
    {
        return [
            'index' => $this->dbName,
            'type' => $this->tbName
        ];
    }

    /**
     * 创建索引 结果["acknowledged": true]
     */
    public function createIndexDetail()
    {
        $params = [
            'index' => $this->dbName, //索引名称
            'body' => [
                'settings' => [ //配置
                    'number_of_shards' => 3,//主分片数
                    'number_of_replicas' => 1 //主分片的副本数
                ],
                'mappings' => [  //映射
                    '_default_' => [ //默认配置，每个类型缺省的配置使用默认配置
                        '_source' => [   //  存储原始文档
                            'enabled' => 'true'
                        ],
                        'properties' => [ //配置数据结构与类型
                            'name' => [ //字段1
                                'type' => 'string',//类型 string、integer、float、double、boolean、date
                                'index' => 'analyzed',//索引是否精确值  analyzed not_analyzed
                            ],
                            'age' => [ //字段2
                                'type' => 'integer',
                            ],
                            'sex' => [ //字段3
                                'type' => 'string',
                                'index' => 'not_analyzed',
                            ],
                        ]
                    ],
                    $this->tbName => [
                        'properties' => [
                            'phone' => [
                                'type' => 'string',
                            ],
                        ]
                    ],
                ],
            ]
        ];
        $res = $this->client->indices()->create($params);
        return $res;
    }

    /*
     * 陈传文
     * 创建索引在设置mapping之前要创建索引
     *
     *
     *
     * */
    public function createIndex()
    {
        try {
            $indexParams = [
                'index' => $this->dbName,
            ];
            $r = $this->client->indices()->create($indexParams);
            return $r;
        } catch (\Exception $e) {
            ErrorModel::throwException(CodeConfigModel::elasticsError);
        }
    }

//    public function create_index()
//    {
//        $indexParams['index'] = 'my_index';
//        $indexParams['type'] = 'my_index';
//        $indexParams['body']['settings']['number_of_shards'] = 2;
//        $indexParams['body']['settings']['number_of_replicas'] = 0;
//        $this->client->create($indexParams);
//    }
    public function add_document()
    {
        $params = array();
        $params['body'] = array(
            'testField' => 'dfdsfdsf'
        );
        $params['index'] = 'my_index';
        $params['type'] = 'my_index';
        $params['id'] = 'w1231313';
        $ret = $this->client->index($params);
    }

    public function delete_index()
    {
        $deleteParams['index'] = 'my_index';
        $this->client->indices()->delete($deleteParams);
    }

    public function deleteDocumentById($docId)
    {
        $deleteParams = array();
        $deleteParams['index'] = $this->dbName;
        $deleteParams['type'] = $this->tbName;
        $deleteParams['id'] = $docId;
        $retDelete = $this->client->delete($deleteParams);
        return $retDelete;
    }

    public function update_document()
    {
        $updateParams = array();
        $updateParams['index'] = 'my_index';
        $updateParams['type'] = 'my_index';
        $updateParams['id'] = 'my_id';
        $updateParams['body']['doc']['asas'] = '111111';
        $response = $this->client->update($updateParams);

    }

    //一般传where就可以了，
    public function searchMatch($where, $pageIndex = ApiConst::pageIndex, $pageSize = ApiConst::pageSize, $sort = array('addTime' => array('order' => 'desc')))
    {
        $searchParams['index'] = $this->dbName;
        $searchParams['type'] = $this->tbName;
        $from = ($pageIndex) * $pageSize;
        $searchParams['from'] = $from;
        $searchParams['size'] = $pageSize;
        $searchParams['sort'] = $sort;
        //must 是与 ，should是或
        $searchParams['body'] = array(
            'query' => $where,
        );
        $retDoc = $this->client->search($searchParams);
        if (!isset($retDoc['hits'])) {
            ErrorModel::throwException(CodeConfigModel::elasticsError);
        }
        $htis = $retDoc['hits']['hits'];
        $returnData['list'] = array_column($htis, '_source');
        $returnData['total'] = $retDoc['hits']['total'];
        return $returnData;
    }

    public function getDocById($id)
    {
        $getParams = array();
        $getParams['index'] = $this->dbName;
        $getParams['type'] = $this->tbName;
        $getParams['id'] = $id;
        $retDoc = $this->client->get($getParams);
        return $retDoc;
    }

    //更新文档
    public function updateDocById($id, $updateArray)
    {
        $params = [
            'index' => $this->dbName,
            'type' => $this->tbName,
            'id' => $id,
            'body' => [
                $updateArray
            ]
        ];
        $res = $this->client->update($params);
        return $res;
    }

    public function deleteDocById($id)
    {
        $getParams = array();
        $getParams['index'] = $this->dbName;
        $getParams['type'] = $this->tbName;
        $getParams['id'] = $id;
        $retDoc = $this->client->delete($id);
        return $retDoc;
    }

    /**
     * 删除索引
     */
    public function deleteIndex()
    {
        try {
            $params = [
                'index' => $this->dbName
            ];
            $res = $this->client->indices()->delete($params);
            return $res;
        } catch (\Exception $ex) {
            throw new \Exception($ex->getMessage(), $ex->getCode());
        }

    }

    /**
     * 删除索引
     */
    public function deleteIndexType()
    {
        $params = [
            'index' => $this->dbName,
            'type' => $this->tbName
        ];

        $res = $this->client->indices()->delete($params);
        return $res;
    }

    /**
     * 删除索引
     */
    public function createDocument($row)
    {
        $params = [
            'index' => $this->dbName,
            'type' => $this->tbName,
            'body' => $row
        ];
        $res = $this->client->index($params);
        return $res;
    }

//插入多条 Document：
    public function postBulkDoc($rows,$key='id')
    {

        foreach ($rows as $row) {
            $params['body'][] = [
                'index' => [
                    '_index' => $this->dbName,
                    '_type' => $row['type']?$row['type']:$this->tbName,
                    '_id'=>$row[$key]
                ]
            ];
            $params['body'][] = $row;
        }
        $res = $this->client->bulk($params);
        return $res;
    }
    public function createIkField($indexFields)
    {
        $params = [
            'index' => $this->dbName, //索引名称
            'body' => [
                'settings' => [ //配置
                    'analysis' => array(
                        'analyzer' => array(
                            'ik' => [
                                'tokenizer' => 'ik_max_word',
                            ]
                        )
                    ),
                ],
                'mappings' => [  //映射
                    $this->tbName => [ //默认配置，每个类型缺省的配置使用默认配置
                        'dynamic' => [   //  存储原始文档
                            'enabled' => 'true'
                        ],
                        'properties' => $indexFields
                    ],
                ],
            ]
        ];
        $res = $this->client->indices()->create($params);
        return $res;
    }
    public function createIndexAndMapping($propertiesField)
    {
        $params = [
            'index' => $this->dbName, //索引名称
            'body' => [
                'mappings' => [  //映射
                    $this->tbName => [ //默认配置，每个类型缺省的配置使用默认配置
                        'properties' => $propertiesField
                    ],
                ],
            ]
        ];
        $res = $this->client->indices()->create($params);
        return $res;
    }
//    public function createIkField($indexFild)
//    {
//        $params = [
//            'index' => $this->dbName, //索引名称
//            'body' => [
//                'settings' => [ //配置
//                    'analysis' => array(
//                        'analyzer' => array(
//                            'ik' => [
//                                'tokenizer' => 'ik_max_word',
//                            ]
//                        )
//                    ),
//                ],
//                'mappings' => [  //映射
//                    $this->tbName => [ //默认配置，每个类型缺省的配置使用默认配置
//                        'dynamic' => [   //  存储原始文档
//                            'enabled' => 'true'
//                        ],
//                        'properties' => [ //配置数据结构与类型
//                            'goodsName' => [ //字段1
//                                "type" => "string",
//                                "analyzer" => "ik_max_word"
//                            ],
//                        ]
//                    ],
//                ],
//            ]
//        ];
//        $res = $this->client->indices()->create($params);
//        return $res;
//    }

    //添加属性
    public function putMappings($column)
    {
        $params = [
            'index' => $this->dbName,
            'type' => $this->tbName,
            'body' => [
                $this->tbName => [
                    'properties' => [
                        $column
                    ]
                ]
            ]
        ];
        $res = $this->client->indices()->putMapping($params);
        return $res;
    }

    public function searchDoc($query)
    {
        $params = [
            'index' => $this->dbName,
            'type' => $this->tbName,
            'body' => [
                'query' => $query
            ]
        ];
        $res = $this->client->search($params);
        return $res;
    }

    public function indexExists()
    {
        try{
            $res =$this->client->exists(array('index'=>$this->dbName));
        }catch(\Exception $ex){
            return false;
        }
        return $res;
    }

//查看mapping
    public function getMappings()
    {
        try {
            $params = [
                'index' => $this->dbName,
            ];
            $res = $this->client->indices()->getMapping($params);
            return $res;
        } catch (\Exception $ex) {
            throw new \Exception($ex->getMessage(), $ex->getCode());
        }

    }

    /**
     * 类实例
     *
     * @var \DAO\UserModel
     */
    private static $_instance = null;


    /**
     * 单例模式获取类实例
     *
     */
    public static function getInstance($type, $index = NameConst::shopkeeper)
    {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new self($index, $type);
        }

        return self::$_instance;
    }

}