<?php
namespace backend\models\searches;

use yii\base\Model;
use yii\data\BaseDataProvider;

class DataTable extends Model
{
    public $draw = 1;
    /**
     * [
     *   0 => ['data' => 'id', 'name' => '', 'searchable' => 'true', 'orderable' => 'true', 'search' => ['value' => '', 'regex' => 'false']],
     *   1 => ['data' => 'name', 'name' => '', 'searchable' => 'true', 'orderable' => 'true', 'search' => ['value' => '', 'regex' => 'false']],
     *   ...
     * ],
     * @var array
     */
    public $columns = [];
    /**
     * [
     *   0 => ['column' => '0', 'dir' => 'desc'],
     * ]
     * @var array
     */
    public $order = [];
    public $start = 0;
    public $length = 20;
    /**
     * ['value' => '', 'regex' => 'false']
     * @var array
     */
    public $search = [];
    /**
     * @var int
     */
    public $batchSize = 5000;

    protected $page;
    protected $pageSize;
    protected $orderBy;

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['draw', 'start', 'length'], 'integer'],
            [['columns', 'order', 'search'], 'safe'],
        ];
    }

    /**
     * 初始化DataTable查询参数
     */
    protected function initSearchParams()
    {
        $length = intval($this->length);
        if ($length <= 0) {
            $length = 20;
        }
        $start = intval($this->start);
        if ($start <= 0) {
            $start = 0;
        }
        $this->pageSize = $length;
        // start=0 => page=1 start=20 page=2...
        $this->page = (int)ceil($start / $length) + 1;
        // 排序
        $columnIndex = isset($this->order[0]['column']) ? trim($this->order[0]['column']) : '';
        $column = isset($this->columns[$columnIndex]['data']) ? trim($this->columns[$columnIndex]['data']) : '';
        $dir = isset($this->order[0]['dir']) ? trim($this->order[0]['dir']) : '';
        if ($column != '' && $dir != '' && in_array(strtolower($dir), ['asc', 'desc'])) {
            $this->orderBy = $column . ' ' . $dir;
        }
    }

    /**
     * @param BaseDataProvider $dataProvider
     * @return array
     */
    public function outResult(BaseDataProvider $dataProvider)
    {
        return [
            'recordsFiltered' => $dataProvider->getTotalCount(),
            'data' => $dataProvider->getModels(),
            'draw' => $this->draw,
            'recordsTotal' => $dataProvider->getTotalCount(),
        ];
    }

    /**
     * 查找所有的话，那么要多次查询
     * @param object $obj API对象
     * @param string $method API方法
     * @param array $data 调用API的参数
     * @param bool $lastRowIsSum API返回的数据的最后一行是统计数据
     * @return array
     */
    public function multiQuery($obj, $method, $data, $lastRowIsSum = true)
    {
        if ($this->pageSize <= $this->batchSize) {
            return call_user_func([$obj, $method], $data);
        }
        set_time_limit(0);
        ini_set('memory_limit', '1024M');
        $dataList = [];
        $resultData = [];
        $summaryRow = [];
        $data['pageSize'] = $this->batchSize;
        $data['page'] = 1;
        while (true) {
            $result = call_user_func([$obj, $method], $data);
            if ($result['code'] == 1 && !empty($result['data']['dataList'])) {
                $dataList = array_merge($dataList, (array)$result['data']['dataList']);
                if ($lastRowIsSum) {
                    $summaryRow = array_pop($dataList);
                }
                unset($result['data']['dataList']);
                $resultData = $result['data'];
            } else {
                break;
            }
            if ($data['page'] * $data['pageSize'] >= $result['data']['totalCount']) {
                break;
            }
            $data['page']++;
        }
        if ($lastRowIsSum && $summaryRow) {
            $dataList[] = $summaryRow;
        }
        $resultData['dataList'] = $dataList;

        return [
            'code' => 1,
            'data' => $resultData,
        ];
    }
}