<?php namespace Collect\Lib;
use Dever;
Dever::apply('autoload', 'querylist', 'vendor');
use QL\QueryList;
class Web
{
    protected $web;
    protected $path;
    protected $domain;
    protected $param = array();

    # 执行某个业务接口
    public function run($web_id, $web_path_id, $param = array())
    {
        $this->web = Dever::db('web', 'collect')->find($web_id);
        if (!$this->web) {
            return false;
        }
        if (isset($param['host'])) {
            $this->web['host'] = $param['host'];
        }
        $this->domain = $this->web['host'];
        $this->path = Dever::db('web_path', 'collect')->find(array('web_id' => $this->web['id'], 'id' => $web_path_id));
        if (!$this->path) {
            return false;
        }
        $this->param = $param;
        return $this->setup();
    }

    # 执行某个业务接口
    protected function setup()
    {
        $col = Dever::db('web_path_col', 'collect')->select(array('web_path_id' => $this->path['id']));
        if ($col) {
            $data = $this->handle($this->path['rule'], $col);
            # 业务处理
            $this->up($this->web['id'], $this->path['id'], $data);
            return $data;
        }
        return 'error';
    }

    protected function handle($range = false, $col = false, $url = false)
    {
        $response = $this->curl($url);
        if ($col && $response) {
            $dom = $this->dom($response);
            return $this->get($dom, $range, $col);
        }
        return false;
    }

    /*
    $reg = [
        'title' => ['.text_box a', 'html'],
        //采集文章标题
        'title' => ['h1','text'],
        //采集文章发布日期,这里用到了QueryList的过滤功能，过滤掉span标签和a标签
        'date' => ['.pt_info','text','-span -a',function($content){
            //用回调函数进一步过滤出日期
            $arr = explode(' ',$content);
            return $arr[0];
        }],
        //采集文章正文内容,利用过滤功能去掉文章中的超链接，但保留超链接的文字，并去掉版权、JS代码等无用信息
        'content' => ['.post_content','html','a -.content_copyright -script']
    ];
    */
    protected function get($dom, $range, $col)
    {
        $rule = array();
        $next = array();
        foreach ($col as $v) {
            if (strstr($v['rule'], '->')) {
                $temp = explode('->', $v['rule']);
                $v['rule'] = $temp[1];
                $next[$temp[0]]['range'] = false;
                $next[$temp[0]]['rule'][] = $v;
                if ($v['attr'] == 'list') {
                    $next[$temp[0]]['range'] = $v['rule'];
                }
                continue;
            }
            
            $rule[$v['key']] = array
            (
                $v['rule'],
                $v['attr'],
                $v['filter'],
            );

            if ($v['callback']) {
                $rule[$v['key']][] = function($content) use ($v) {
                    if (!strstr($v['callback'], '(')) {
                        $v['callback'] .= '({c})';
                    }
                    
                    if (strstr($v['callback'], '{c}')) {
                        $v['callback'] = str_replace('{c}', '$content', $v['callback']);
                    }
                    if (strstr($v['callback'], '{domain}')) {
                        $v['callback'] = str_replace('{domain}', '$this->domain', $v['callback']);
                    }
                    $call = '$content =' . $v['callback'] . ';';
                    eval($call);
                    return $content;
                };
            }
        }

        $dom = $dom->rules($rule);
        if ($range) {
            $dom = $dom->range($range);
        }

        $data = $dom->queryData();
        $test = Dever::input('test');
        if ($data && $next) {
            foreach ($data as $k => $v) {
                foreach ($next as $k1 => $v1) {
                    if (isset($v[$k1]) && $v[$k1]) {
                        $data[$k] += $this->handle($v1['range'], $v1['rule'], $v[$k1]);
                    }
                }
                if ($test == 1 && $k == 0) {
                    print_r(Dever::load('common', 'collect')->table($data[0]));die;
                }
            }
        }
        return $data;
    }

    protected function dom($html)
    {
        if (strstr($html, 'gb2312')) {
            $html = str_replace('gb2312', 'utf-8', $html);
        }
        return QueryList::html($html);
    }

    # 发起请求
    protected function curl($url = false)
    {
        if (!$url) {
            if (strstr($this->path['uri'], 'http')) {
                $this->web['host'] = '';
            }
            $url = $this->web['host'] . $this->path['uri'];
        }
        $response = Dever::curl($url)->result();
        $response = $this->filter($response);
        return $response;
    }
    protected function filter($data)
    {
        return preg_replace("/<!--[^\!\[]*?(?<!\/\/)-->/","",$data);
    }

    # 获取后台展示需要的数据
    public function getData($where, $set)
    {
        $web_path_id = Dever::input('set')['web_path_id'];
        $where['web_path_id'] = $web_path_id;
        $info = Dever::db('web_data', 'collect')->select($where, $set);
        $data['head'] = $data['body'] = array();
        $col = Dever::db('web_path_col', 'collect')->select(array('web_path_id' => $web_path_id, 'status' => 1));
        if (!$col || !$info) {
            return $data;
        }
        $config = array();
        foreach ($col as $k => $v) {
            $config['field'][$v['key']] = array('name' => $v['key'], 'type' => 'show');
        }

        $page = Dever::load('common', 'manage')->page('collect/web_data', $config);
        $data['field'] = $page->setting('field', $data['head']);
        foreach ($info as $k => $v) {
            $body = array();
            $content = Dever::json_decode($v['value']);
            foreach ($content as $key => $value) {
                if (isset($config['field'][$key])) {
                    $body[$key] = $page->getValue($key, $value, $content);
                    $button = $page->button('data_button', $v);
                    if ($button) {
                        $body['button'] = $button;
                    }
                }
            }
            $body['id'] = $v['id'];
            $data['body'][] = $body;
        }
        return $data;
    }

    public function value($id)
    {
        $info = Dever::db('web_data', 'collect')->one($id);
        $data = Dever::json_decode($info['value']);
        $result = array();
        if (!$data) {
            return '';
        }
        $col = Dever::db('web_path_col', 'collect')->select(array('web_path_id' => $info['web_path_id']));
        if ($col) {
            $temp = array();
            foreach ($col as $k => $v) {
                $temp[$v['key']] = $v;
            }
            foreach ($data as $k => $v) {
                if (isset($temp[$k]) && $temp[$k]) {
                    $result[$temp[$k]['name'] . '('.$k.')'] = $v;
                } else {
                    $result[$k] = $v;
                }
            }
        } else {
            $result = $data;
        }
        
        return Dever::load('common', 'collect')->table($result);
    }
    
    # 更新数据
    public function up($web_id, $web_path_id, $value)
    {
        $data['web_id'] = $web_id;
        $data['web_path_id'] = $web_path_id;
        if (isset($value[0]) && $value[0]) {
            foreach ($value as $v) {
                $this->insert($data, $v);
            }
        } else {
            $this->insert($data, $value);
        }
    }

    protected function insert($data, $value)
    {
        $data['value'] = Dever::json_encode($value);
        $info = Dever::db('web_data', 'collect')->find($data);
        if (!$info) {
            Dever::db('web_data', 'collect')->insert($data);
        }
    }

    # 清空数据
    public function drop_api()
    {
        $where['web_id'] = Dever::input('id');
        Dever::db('web_data', 'collect')->delete($where);

        return 'reload';
    }

    # 导出excel
    public function excel()
    {
        $where['info_id'] = Dever::input('id');
        $data = Dever::db('spider/data')->select($where);
        
        if (!$data) {
            return '';
        }
        $col = Dever::db('spider/col')->select($where);
        $set = Dever::db('spider/set')->select($where);

        $info = Dever::db('spider/project')->find($where['pid']);
        $file = $info['name'] . '的采集数据';
        $header = $body = array();

        if ($col) {
            foreach ($col as $k => $v) {
                $header[] = $v['name'];
            }
        }

        if ($set) {
            foreach ($set as $k => $v) {
                $header[] = $v['name'];
            }
        }

        if ($data) {
            $i = 0;
            foreach ($data as $k => $v) {

                if (!$v['value']) {
                    continue;
                }
                $value = Dever::json_decode($v['value']);
                if (!$value) {
                    continue;
                }
                if ($col) {
                    foreach ($col as $k => $v) {
                        $body[$i][] = isset($value[$v['key']]) ? $value[$v['key']] : '';
                    }
                }

                if ($set) {
                    foreach ($set as $k => $v) {
                        $body[$i][] = isset($value[$v['key']]) ? $value[$v['key']] : '';
                    }
                }
                $i++;
            }
        }

        Dever::excelExport($body, $header, $file);
    }

    public function view($page)
    {
        # 这里获取基本信息
        $value = Dever::json_decode($page->info['value']);
        $content = array();
        foreach ($value as $k => $v) {
            $content[] = array
            (
                'name' => $k,
                # 类型，text普通文本，tag标签，link链接，image图片 progress进度条 stat统计 timeline时间线 table表格
                'type' => 'text',
                'content' => $v,
                # 样式primary success warning danger info exception
                //'style' => 'info',
            );
        }
        $info[] = array
        (
            # 类型，desc描述 table表格，表格有head和body即可
            'type' => 'desc',
            'name' => '详细信息',
            # 每行展示数量
            'column' => 1,
            # 是否有边框
            'border' => true,
            # 排列方向：horizontal横向 vertical纵向
            'direction' => 'horizontal',
            'content' => $content,
        );

        return array('info' => $info);
    }
}