<?php

namespace TdyCommons;

use TdyCommons\Table\Settings;
use Zend\Db\Adapter\Adapter as DbAdapter;
use Zend\Db\ResultSet\HydratingResultSet;
use Zend\Db\TableGateway\TableGateway;
use Zend\Log\Formatter\Simple as SimpleFormatter;
use Zend\Log\Logger;
use Zend\Log\Writer\Db as LogWriterDb;
use Zend\Log\Writer\Stream as LogWriterStream;
use Zend\Log\Filter\Priority as LogFilterPriority;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\ModuleManager\Feature\ServiceProviderInterface;
use Zend\ModuleManager\Feature\ViewHelperProviderInterface;
use Zend\Mvc\Router\Http\RouteMatch;
use Zend\ServiceManager\AbstractPluginManager;
use Zend\ServiceManager\ServiceLocatorInterface;

class Module implements AutoloaderProviderInterface, ConfigProviderInterface, ServiceProviderInterface, ViewHelperProviderInterface
{

    public function getConfig()
    {
        $general = include __DIR__ . '/config/general.php';
        $db      = include __DIR__ . '/config/db.php';

        return array_merge($general, $db);
    }

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

    public function getViewHelperConfig()
    {
        return [
            'factories' => [
                'settings'   => function (AbstractPluginManager $pm) {
                    /** @var Settings $table */
                    $table  = $pm->getServiceLocator()->get('TdyCommons\Table\Settings');
                    $helper = new View\Helper\Settings();
                    $helper->setTable($table);

                    return $helper;
                },
                'copyright'  => function (AbstractPluginManager $pm) {
                    /** @var Settings $table */
                    $table  = $pm->getServiceLocator()->get('TdyCommons\Table\Settings');
                    $helper = new View\Helper\Copyright();
                    $helper->setTable($table);

                    return $helper;
                },
                'module'     => function (AbstractPluginManager $pm) {
                    $locator = $pm->getServiceLocator();
                    $match   = $locator->get('application')->getMvcEvent()->getRouteMatch();
                    $helper  = new View\Helper\Module();
                    $helper->setRouteMatch($match);

                    return $helper;
                },
                'routeParam' => function (AbstractPluginManager $pm) {
                    $locator = $pm->getServiceLocator();
                    /** @var RouteMatch $match */
                    $match  = $locator->get('application')->getMvcEvent()->getRouteMatch();
                    $helper = new View\Helper\RouteParam();
                    $helper->setRouteMatch($match);

                    return $helper;
                },
            ],
        ];
    }

    public function getServiceConfig()
    {
        return [
            'factories' => [
                'TdyCommons\Table\Settings'      => function (ServiceLocatorInterface $sm) {
                    /** @var DbAdapter $dbAdapter */
                    $dbAdapter = $sm->get('db-01');
                    $tableName = $sm->get('Config')['mappings']['tables']['settings']['name'];
                    $columns   = $sm->get('Config')['mappings']['tables']['settings']['columns'];

                    $resultSetProto = new HydratingResultSet();
                    $resultSetProto->setObjectPrototype(new Model\Setting());
                    $tableGateway = new TableGateway($tableName, $dbAdapter, null, $resultSetProto);
                    $table        = new Table\Settings($tableGateway, $columns);

                    return $table;
                },
                'TdyCommons\Table\DropdownLists' => function (ServiceLocatorInterface $sm) {

                    /** @var DbAdapter $dbAdapter */
                    $dbAdapter = $sm->get('db-01');
                    $tableName = $sm->get('Config')['mappings']['tables']['dropdown-lists']['name'];
                    $columns   = $sm->get('Config')['mappings']['tables']['dropdown-lists']['columns'];
                    $logger    = $sm->get('Logger');

                    $resultSetProto = new HydratingResultSet();
                    $resultSetProto->setObjectPrototype(new Model\DropdownList());
                    $tableGateway = new TableGateway($tableName, $dbAdapter, null, $resultSetProto);
                    $table        = new Table\DropdownLists($tableGateway, $columns);
                    $table->setLogger($logger);

                    return $table;
                },
                'TdyCommons\Table\DropdownItems' => function (ServiceLocatorInterface $sm) {
                    /** @var DbAdapter $dbAdapter */
                    $dbAdapter = $sm->get('db-01');
                    $tableName = $sm->get('config')['mappings']['tables']['dropdown-items']['name'];
                    $columns   = $sm->get('config')['mappings']['tables']['dropdown-items']['columns'];

                    $resultSetProto = new HydratingResultSet();
                    $resultSetProto->setObjectPrototype(new Model\Option());
                    $tableGateway = new TableGateway($tableName, $dbAdapter, null, $resultSetProto);
                    $table        = new Table\Options($tableGateway, $columns);

                    return $table;
                },
                'Logger'                         => function (ServiceLocatorInterface $sm) {
                    /** @var array $config */
                    $config   = $sm->get('config');
                    $priority = isset($config['logging']['priority']) ? $config['logging']['priority'] : Logger::DEBUG;

                    $log = new Logger();

                    $filename   = 'debug-' . date('Y-m-d') . '.log';
                    $fileWriter = new LogWriterStream('./data/logs/' . $filename);
                    $filter     = new LogFilterPriority($priority);
                    $fileWriter->addFilter($filter);

                    $format    = '%timestamp% P%priority%: %message%';
                    $formatter = new SimpleFormatter($format);
                    $fileWriter->setFormatter($formatter);

                    /** @var DbAdapter $dbAdapter */
                    $dbAdapter = $sm->get('db-01');
                    $tableName = $sm->get('Config')['mappings']['tables']['logs-admin']['name'];
                    $columns   = $sm->get('Config')['mappings']['tables']['logs-admin']['columns'];
                    $mapping   = [
                        'timestamp'    => $columns['timestamp'],
                        'priorityName' => $columns['level'],
                        'message'      => $columns['message']
                    ];
                    $dbWriter  = new LogWriterDb($dbAdapter, $tableName, $mapping);
                    $filter    = new LogFilterPriority(Logger::INFO);
                    $dbWriter->addFilter($filter);

                    $log->addWriter($fileWriter);
                    $log->addWriter($dbWriter);

                    return $log;
                },
            ],
        ];
    }

}
