<?php

namespace Application;

use Application\Session\Container;
use Zend\Http\Response as HttpResponse;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\ModuleManager\Feature\ViewHelperProviderInterface;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
use Zend\Mvc\Router\RouteMatch;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Session;

class Module implements AutoloaderProviderInterface, ConfigProviderInterface, ViewHelperProviderInterface
{

    public function onBootstrap(MvcEvent $e)
    {
        $sm          = $e->getApplication()->getServiceManager();
        $phpSettings = $sm->get('config')['php-settings'];

        if ($phpSettings) {
            foreach ($phpSettings as $key => $value) {
                ini_set($key, $value);
            }
        }

        $tz = ini_get('date.timezone');
        date_default_timezone_set($tz);

        $eventManager = $e->getApplication()->getEventManager();
        $eventManager->attach(MvcEvent::EVENT_ROUTE, [$this, 'checkLogin'], -3);
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);

        $this->bootstrapSession($e);
    }

    public function bootstrapSession(MvcEvent $e)
    {
        $session = $e->getApplication()->getServiceManager()->get('Zend\Session\SessionManager');

        try {
            $session->start();

            $container = new Container(SESSION_CONTAINER);
            if ($container->init == 0) {

                /** @var ServiceLocatorInterface $serviceManager */
                $serviceManager = $e->getApplication()->getServiceManager();
                $request        = $serviceManager->get('Request');

                $session->regenerateId(false);
                $container->init          = 1;
                $container->remoteAddr    = $request->getServer()->get('REMOTE_ADDR');
                $container->httpUserAgent = $request->getServer()->get('HTTP_USER_AGENT');

                $config = $serviceManager->get('config');
                if (!isset($config['session'])) {
                    return;
                }

                $sessionConfig = $config['session'];
                if (isset($sessionConfig['validators'])) {
                    /** @var Session\ValidatorChain $chain */
                    $chain = $session->getValidatorChain();

                    foreach ($sessionConfig['validators'] as $validator) {
                        switch ($validator) {
                            case 'Zend\Session\Validator\HttpUserAgent':
                                $validator = new $validator($container->httpUserAgent);
                                break;
                            case 'Zend\Session\Validator\RemoteAddr':
                                $validator = new $validator($container->remoteAddr);
                                break;
                            default:
                                $validator = new $validator();
                        }

                        $chain->attach('session.validate', [$validator, 'isValid']);
                    }
                }

            }
        } catch (\Exception $ex) {
            $session->destroy();

            $url = $e->getRouter()->assemble(
                [
                    'action'     => 'login',
                    'controller' => 'tdyadmins\controller\logging',
                    'module'     => 'TdyAdmins'
                ],
                [
                    'name' => 'login'
                ]
            );

            /** @var HttpResponse $response */
            $response = $e->getResponse();
            $response->getHeaders()->addHeaderLine('Location', $url);
            $response->setStatusCode(302);
        }
    }

    public function checkLogin(MvcEvent $e)
    {
        $match = $e->getRouteMatch();

        if (!$match instanceof RouteMatch) {
            return;
        }

        $controller = strtolower($match->getParam('controller'));
        $action     = $match->getParam('action');

        $whiteList = [
            'application\controller\index'  => ['index', 'script'],
            'tdyplayers\controller\logging' => ['login', 'html', 'script', 'signup', 'signupScript', 'toc'],
        ];


        if (array_key_exists($controller, $whiteList) && in_array($action, $whiteList[$controller])) {
            return;
        } else {
            $session = new Container(SESSION_CONTAINER);
            if (isset($session->user) && $session->user != null) {
                return;
            } else {
                $url = $e->getRouter()->assemble(
                    [
                        'action'     => 'login',
                        'controller' => 'tdyplayers\controller\logging',
                        'module'     => 'TdyPlayers'
                    ],
                    [
                        'name' => 'login'
                    ]
                );

                /** @var HttpResponse $response */
                $response = $e->getResponse();
                $response->getHeaders()->addHeaderLine('Location', $url);
                $response->setStatusCode(302);
            }
        }
    }

    public function getConfig()
    {
        return include __DIR__ . '/config/general.php';
    }

    public function getAutoloaderConfig()
    {
        return [
            'Zend\Loader\StandardAutoloader' => [
                'namespaces' => [
                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                ],
            ],
        ];
    }

    public function getViewHelperConfig()
    {
        return [
            'factories' => [],
        ];
    }

    public function getServiceConfig()
    {
        return [
            'factories' => [
                'Zend\Session\SessionManager' => function (ServiceLocatorInterface $sm) {
                    $config = $sm->get('config');
                    if (isset($config['session'])) {
                        $session = $config['session'];

                        $sessionConfig = null;
                        if (isset($session['config'])) {
                            $class   = isset($session['config']['class']) ? $session['config']['class'] : 'Zend\Session\Config\SessionConfig';
                            $options = isset($session['config']['options']) ? $session['config']['options'] : [];

                            /** @var Session\Config\ConfigInterface $sessionConfig */
                            $sessionConfig = new $class();
                            $sessionConfig->setOptions($options);
                        }

                        $sessionStorage = null;
                        if (isset($session['storage'])) {
                            $class          = $session['storage'];
                            $sessionStorage = new $class();
                        }

                        $sessionSaveHandler = null;
                        if (isset($session['save_handler'])) {
                            $sessionSaveHandler = $sm->get($session['save_handler']);
                        }

                        $sessionManager = new Session\SessionManager($sessionConfig, $sessionStorage, $sessionSaveHandler);
                    } else {
                        $sessionManager = new Session\SessionManager();
                    }
                    Container::setDefaultManager($sessionManager);

                    return $sessionManager;
                },
            ],
        ];
    }

}