<?php namespace Majestic\Session;
/**
 * @copyright NetMonsters <team@netmonsters.ru>
 * @link http://netmonsters.ru 
 * @package Majestic
 * @subpackage session
 * @since 2010-03-14
 */

class Session
{
    /**
     * Default number of seconds the session will be remembered 
     * for when asked to be remembered
     *
     * @var int
     */
    private static $remember_time = 1209600; // 2 weeks
    
    private static $started = false;
    
    /**
     * Avoid new
     * @codeCoverageIgnoreStart
     */
    private function __construct(){}

    /**
     * @codeCoverageIgnoreEnd
     */

    /**
     * Avoid cloning
     * @codeCoverageIgnoreStart
     */
    private function __clone(){}

    /**
     * @codeCoverageIgnoreEnd
     */

    /**
     * Retrieve a member of the $_SESSION
     *
     * If no $key is passed, returns the entire $_SESSION array.
     *
     * @param string $key
     * @param mixed $default Default value to use if key not found
     * @return mixed Returns null if key does not exist
     */
    public static function get($key = null, $default = null)
    {
        if (!self::$started) {
            if (self::isExists()) {
                self::start();
            } else {
                return $default;
            }
        }
        if (null === $key) {
            return $_SESSION;
        }
        return isset($_SESSION[$key]) ? $_SESSION[$key] : $default;
    }
    
    /**
     * Set $_SESSION values
     *
     * @param  string|array $spec
     * @param  null|mixed $value
     * @return void
     */
    public static function set($spec, $value = null)
    {
        if (!self::$started) {
            self::start();
        }
        if (is_array($spec)) {
            foreach ($spec as $key => $value) {
                self::set($key, $value);
            }
            return;
        }
        $_SESSION[(string) $spec] = $value;
    }
    
    /**
     * Delete Session value
     * 
     * @param string $key
     */
    public static function del($key)
    {
        if (!self::$started) {
            if (self::isExists()) {
                self::start();
            } else {
                return;
            }
        }
        if (isset($_SESSION[$key])) {
            unset($_SESSION[$key]);
        }
    }

    /**
     * remember() - Write a persistent cookie that expires after a number 
     * of seconds in the future. If no number of seconds is specified, 
     * then this defaults to self::$rememberMeSeconds.
     *
     * @param $seconds integer - OPTIONAL specifies TTL for cookie in seconds from present time
     * @return void
     */
    public static function remember($seconds = null)
    {
        $seconds = (int) $seconds;
        $seconds = ($seconds > 0) ? $seconds : self::$remember_time;
        self::rememberUntil($seconds);
    }

    /**
     * forget() - Write a volatile session cookie, removing any persistent 
     * cookie that may have existed. The session would end upon, 
     * for example, termination of a web browser program.
     *
     * @return void
     */
    public static function forget()
    {
        self::rememberUntil();
    }

    /**
     * rememberUntil() - This method does the work of changing the state of the session 
     * cookie and making sure that it gets resent to the browser via regenerateId()
     *
     * @param int $seconds
     * @return void
     */
    public static function rememberUntil($seconds = 0)
    {
        $params = session_get_cookie_params();
        session_set_cookie_params(
            $seconds,
            $params['path'],
            $params['domain'],
            $params['secure']
        );
        self::regenerateId();
    }
    
    /**
     * regenerateId() - Regenerate the session id.  Best practice is to call this after
     * session is started.  If called prior to session starting, session id will be regenerated
     * at start time.
     *
     * @throws Zend_Session_Exception
     * @return void
     */
    public static function regenerateId()
    {
        if (self::$started) {
            session_regenerate_id(true);
        }
    }

    public static function isExists()
    {
        if (isset($_COOKIE[session_name()])) {
            return true;
        }
        return false;
    }

    public static function start()
    {
        if (self::$started) {
            return;
        }
        self::$started = true;
        @session_start();
    }

    /**
     * getId() - get the current session id
     *
     * @return string
     */
    public static function getId()
    {
        return session_id();
    }

    /**
     * destroy() - This is used to destroy session data, and optionally, 
     * the session cookie itself
     *
     * @param bool $remove_cookie - OPTIONAL remove session id cookie, 
     *                              defaults to true (remove cookie)
     * @return void
     */
    public static function destroy($remove_cookie = true)
    {
        session_destroy();
        if ($remove_cookie) {
            self::expireSessionCookie();
        }
    }


    /**
     * expireSessionCookie() - Sends an expired session id cookie, causing the client to delete the session cookie
     *
     * @return void
     */
    public static function expireSessionCookie()
    {
        if (isset($_COOKIE[session_name()])) {
            $params = session_get_cookie_params();
            setcookie(
                session_name(),
                false,
                0,
                $params['path'],
                $params['domain'],
                $params['secure']
            );
        }
    }
    
    public static function setSessionHandler($handler)
    {
        session_set_save_handler(
            array($handler, 'open'),
            array($handler, 'close'),
            array($handler, 'read'),
            array($handler, 'write'),
            array($handler, 'destroy'),
            array($handler, 'gc')
        );
    }
}