<?php

namespace ciy;

class sql {
    public $tsmt;
    public $table;
    public $column;
    public $limit;
    public $where;
    public $order;
    public $selecttail;
    public $err;
    public $wrapup;

    function __construct($table = '') {
        $this->tsmt = array();
        $this->table = $table;
        $this->column = '*';
        $this->limit = '';
        $this->where = '';
        $this->order = '';
        $this->selecttail = '';
        $this->err = '';
        $this->wrapup = true;
    }
    function column($column, $fields = null) {
        if ($column[0] == '!') {
            if (!is_array($fields))
                return $this;
            $excols = explode(',', substr($column, 1));
            $cols = array();
            foreach ($fields as $fr) {
                if (in_array($fr['Field'], $excols))
                    continue;
                $cols[] = $fr['Field'];
            }
            $column = implode(',', $cols);
        }
        $this->column = $column;
        return $this;
    }
    function limit($pageno, $pagecount = 20) {
        if ($pageno < 1)
            $pageno = 1;
        if ($pagecount < 1)
            $pagecount = 20;
        $pageid = $pagecount * ($pageno - 1);
        $this->limit = " limit {$pageid},{$pagecount}";
        return $this;
    }
    function order($order) {
        $chks = explode(',', $order);
        foreach ($chks as $chk) {
            if (substr($chk, -5) == ' desc')
                $chk = trim(substr($chk, 0, -5));
            if (!preg_match('/^[0-9a-zA-Z_\-\.]+$/', $chk))
                return $this;
        }
        $this->order = $order;
        return $this;
    }
    function selecttail($selecttail) {
        $this->selecttail = $selecttail;
        return $this;
    }
    function where($query, $data = null) {
        $this->where .= $this->_query($query, $data);
        return $this;
    }
    static public function daterange($data, $type = 'date') {
        $ret = [-1, -1];
        if ($type == 'date') {
            $ds = explode('~', $data);
            if (count($ds) == 2) {
                $ds[0] = trim($ds[0]);
                if (!empty($ds[0])) {
                    if (strpos($ds[0], ':') === false)
                        $ds[0] .= ' 00:00:00';
                    $dt = strtotime($ds[0]);
                    if ($dt !== false)
                        $ret[0] = $dt;
                }
                $ds[1] = trim($ds[1]);
                if (!empty($ds[1])) {
                    if (strpos($ds[1], ':') === false)
                        $ds[1] .= ' 23:59:59';
                    $dt = strtotime($ds[1]);
                    if ($dt !== false)
                        $ret[1] = $dt;
                }
            }
        } else if ($type == 'day') {
            $ds = explode('~', $data);
            if (count($ds) == 2) {
                $ds[0] = trim($ds[0]);
                if ($ds[0] != '') {
                    $ret[0] = strtotime(date('Y-m-d 00:00:00')) + toint($ds[0]) * 86400;
                }
                $ds[1] = trim($ds[1]);
                if ($ds[1] != '') {
                    $ret[1] = strtotime(date('Y-m-d 23:59:59')) + toint($ds[1]) * 86400;
                }
            }
        } else if ($type == 'month') {
            if (!empty($data)) {
                $dayt = strtotime($data . '-1 0:0:0');
                if ($dayt !== false) {
                    $ret[0] = $dayt;
                    $ret[1] = strtotime('+1 month', $dayt) - 1;
                }
            }
        }
        return $ret;
    }
    function wheredaterange($query, $data, $type = 'date') { //date '2010-1-1 0:0:0 ~ 2011-2-1'     day:  -30~0
        if ($type == 'date') {
            $ds = explode('~', $data);
            if (count($ds) == 2) {
                $ds[0] = trim($ds[0]);
                if (!empty($ds[0])) {
                    if (strpos($ds[0], ':') === false)
                        $ds[0] .= ' 00:00:00';
                    $dt = strtotime($ds[0]);
                    if ($dt !== false)
                        $this->where($query . '>=', $dt);
                }
                $ds[1] = trim($ds[1]);
                if (!empty($ds[1])) {
                    if (strpos($ds[1], ':') === false)
                        $ds[1] .= ' 23:59:59';
                    $dt = strtotime($ds[1]);
                    if ($dt !== false)
                        $this->where($query . '<=', $dt);
                }
            }
        } else if ($type == 'day') {
            $dayt = toint($data);
            if ($dayt > 0) {
                $this->where($query . '>=', $dayt);
                $this->where($query . '<', $dayt + 86400);
            }
        } else if ($type == 'month') {
            $dayt = toint($data);
            if ($dayt > 0) {
                $this->where($query . '>=', $dayt);
                $dayt = strtotime('+1 month', $dayt);
                $this->where($query . '<', $dayt);
            }
        }
        return $this;
    }
    function wherenumrange($query, $data1, $data2, $bet = 1) {
        if ($data1 !== '') {
            $this->where .= $this->_query($query . '>=', (float)$data1 * $bet);
        }
        if ($data2 !== '') {
            $this->where .= $this->_query($query . '<=', (float)$data2 * $bet);
        }
        return $this;
    }
    function wherenumber($query, $data, $bet = 1) {
        $data = trim($data);
        if (empty($data)) {
            $this->err = 'wherenumber data null';
            return $this;
        }
        if (strpos($data, '~') !== false) {
            $ds = explode('~', $data);
            if (!empty($ds[0]))
                $this->where .= $this->_query($query . '>=', (float)$ds[0] * $bet);
            if (!empty($ds[1]))
                $this->where .= $this->_query($query . '<=', (float)$ds[1] * $bet);
        } else if (strpos($data, ',') !== false) {
            $datas = explode(',', $data);
            $ids = array();
            foreach ($datas as $d)
                $ids[] = toint($d);
            $data = implode(',', $ids);
            $this->where .= $this->_query($query . ' in', $data);
        } else if ($data[0] == '>' || $data[0] == '<' || $data[0] == '=') {
            if (($data[0] == '<' && @$data[1] == '>') || @$data[1] == '=') {
                $query .= substr($data, 0, 2);
                $data = (float)substr($data, 2);
            } else {
                $query .= substr($data, 0, 1);
                $data = (float)substr($data, 1);
            }
            $this->where .= $this->_query($query, $data * $bet);
        } else {
            $this->where .= $this->_query($query, $data * $bet);
        }
        return $this;
    }
    function _query($query, $data = null) {
        if (empty($query)) {
            $this->err = '_query query null';
            return '';
        }
        if ($data === null) {
            if ($query == 'id')
                return 'id=0'; //防止误操作
            return ' and ' . $query;
        }
        $cnt = substr_count($query, '?');
        if ($cnt > 0) {
            if ($query[0] != ' ')
                $query = ' and ' . $query;
            if (!is_array($data)) {
                if ($cnt == 1) {
                    $this->tsmt[] = $data;
                    return $query;
                }
                $this->err = '_query data length error';
                return '';
            }
            if (count($data) != $cnt) {
                $this->err = '_query data length mismatch';
                return '';
            }
            foreach ($data as $d)
                $this->tsmt[] = $d;
            return $query;
        }
        $query = trim($query);
        if (substr($query, -5) == ' like') {
            if ($data === '' || $data === ',,')
                return '';
            if ($data[0] != '%' && $data[strlen($data) - 1] != '%')
                $data = "%{$data}%";
            $query = " and {$query} ?";
        } else if (substr($query, -3) == ' in') {
            if (is_array($data))
                $data = implode(',', $data);
            if ($data === '')
                return '';
            return " and {$query} ({$data})";
        } else {
            $t = substr($query, -1);
            if ($t != '=' && $t != '>' && $t != '<') {
                if ($data === '')
                    return '';
                $query .= '=';
            }
            $query = " and {$query}?";
        }
        $this->tsmt[] = $data;
        return $query;
    }
    function buildsql() {
        if (empty($this->table))
            return null;
        $sql = "select {$this->column} from {$this->table}";
        $sql .= $this->buildwhere();
        if (!empty($this->order))
            $sql .= ' order by ' . $this->order;
        if (!empty($this->selecttail))
            $sql .= ' ' . $this->selecttail;
        return $sql;
    }
    function buildwhere() {
        if (empty($this->where))
            return '';
        if (strpos($this->where, ' and ') === 0)
            $this->where = substr($this->where, 5);
        return ' where ' . $this->where;
    }
}
