<?php

/**
 * Created by PhpStorm.
 * User: stanley-king
 * Date: 16/1/30
 * Time: 下午3:43
 */
class session
{
    static $stInstance = NULL;
    private $fdestroy = false;
    private $sessid = '';

    const prefix = 'MPHPSESSID';
    const session_name = 'MPHPSESSID';

    static public function instance()
    {
        if(self::$stInstance == NULL) {
            self::$stInstance = new session();
        }
        return self::$stInstance;
    }

    private function __construct()
    {
    }

    public function init()
    {
        session_set_save_handler(
            array(&$this,'onOpen'),
            array(&$this,'onClose'),
            array(&$this,'onRead'),
            array(&$this,'onWrite'),
            array(&$this,'onDestroy'),
            array(&$this,'onGc'));
    }

    public function start()
    {
        $this->fdestroy = false;
        session_start();
        $_SESSION['MPHPSESSID'] = $this->sessid;
    }

    public function end()
    {
        // 会触发write 和 close 函数
        session_write_close();

        foreach($_SESSION as $key=>$value) {
            unset($_SESSION[$key]);
        }
        foreach($_COOKIE as $key=>$value) {
            unset($_COOKIE[$key]);
        }
        foreach($_POST as $key => $value) {
            unset($_POST[$key]);
        }
        foreach($_GET as $key => $value) {
            unset($_GET[$key]);
        }
        request_helper::clear_server();
        $this->sessid = '';
    }

    public function destroy() {
        $this->fdestroy = true;
        $sid = $this->sessid;
        fcgi_setcookie("MPHPSESSID","{$sid}", -3600,'/',LOCAL_DOMAIN);
    }

    public function onOpen() {
        return true;
    }
    public function onRead($rsid)
    {
        //这段代码为了确保内置H5，直接使用客户端的session 状态。
        $client = strtolower(trim($_SERVER['HTTP_CLIENT_TYPE']));
        if($client == 'ios' || $client == 'android')
        {
            $sid = $_COOKIE[self::session_name];
            Log::record("APP MPHPSESSID = {$sid}." , Log::DEBUG);
            return $this->from_certain($sid);
        }
        else
        {
            $sid = $_COOKIE[self::session_name];
            Log::record("WAP MPHPSESSID = {$sid}." , Log::DEBUG);

            if(isset($_POST['HPHPSESSID']) && !empty($_POST['HPHPSESSID']))
            {
                $hsid = $_POST['HPHPSESSID'];
                $this->sessid = $hsid;
                if($sid == $hsid) {
                    return $this->from_certain($sid);
                } else {
                    return $this->from_uncertain($hsid);
                }
            }
            else
            {
                return $this->from_certain($sid);
            }
        }
    }
    private function from_uncertain($sid)
    {
        $this->set_cookie($sid);
        if(empty($sid))
        {
            return '';
        }
        else
        {
            $data = rcache($sid,self::prefix);
            if(empty($data)) {
                return '';
            } else {
                $this->sessid = $sid;
                return $data[self::session_name];
            }
        }
    }

    private function from_certain($sid)
    {
        if(empty($sid))
        {
            $ret = session_regenerate_id(false);
            if($ret == true) {
                $sid = session_id();
                $this->set_cookie($sid);
                $this->sessid = $sid;
            } else {
                Log::record("session_regenerate_id error.",Log::ERR);
            }

            return '';
        }
        else
        {
            $data = rcache($sid,self::prefix);
            if(empty($data))
            {
                dcache($sid,self::prefix);
                $ret = session_regenerate_id(false);
                if($ret == true) {
                    $sid = session_id();
                    $this->set_cookie($sid);
                    $this->sessid = $sid;
                } else {
                    Log::record("session_regenerate_id error.",Log::ERR);
                }

                return '';
            } else {
                $this->sessid = $sid;
                return $data[self::session_name];
            }
        }
    }

    public function onClose() {
        return true;
    }

    public function onWrite($sid, $data)
    {
        if($this->fdestroy) {
            dcache($this->sessid,self::prefix);
        } else {
            wcache($this->sessid,array(self::session_name => $data),self::prefix,self::expire_min());
        }

        return true;
    }

    public function onDestroy($sid) {
        return dcache($this->sessid,self::prefix);
    }

    public function onGc($expire) {
        return true;
    }

    public function set_cookie($sid)
    {
        $expire_time = time() + self::expire_min() * 60;
        fcgi_setcookie("MPHPSESSID","{$sid}",$expire_time,'/',LOCAL_DOMAIN);
    }

    private static function expire_min()
    {
        if(is_debug()) {
            return 43200;
        } else {
            return 43200;
        }
    }

    static public function read_other_session($sid)
    {
        $data = rcache($sid,self::prefix);
        $org = $_SESSION;
        $_SESSION = [];
        if(session_decode($data[self::session_name]) == true) {
            $data = $_SESSION;
            $_SESSION = $org;
            return $data;
        } else {
            $_SESSION = $org;
            return false;
        }
    }
    static public function write_other_session($sid,$data)
    {
        $org = $_SESSION;
        $_SESSION = $data;
        $data = session_encode();
        wcache($sid,array(self::session_name => $data),self::prefix,self::expire_min());
        $_SESSION = $org;
    }
}