<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonCommon\Classes;

use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger;
use Shopware\Components\DependencyInjection\Container;

class LoggerFactory
{
    /**
     * @var Container
     */
    private $container;

    /**
     * @param Container $container
     */
    public function __construct(Container $container)
    {
        $this->container = $container;
    }

    /**
     * Create a new Logger instance that logs similar to Shopware's plugin logger.
     *
     * The processors and handlers are the same as for Shopware's plugin logger.
     *
     * @param string $name
     * @param string $logLevel
     * @return Logger
     */
    public function createLikePluginLogger($name, $logLevel)
    {
        $logDir = $this->container->getParameter('kernel.logs_dir');
        $environment = $this->container->getParameter('kernel.environment');
        $fileName = sprintf('%s/%s_%s.log', $logDir, $name, $environment);

        $handler = new RotatingFileHandler($fileName, 14, $logLevel);
        $logger = new Logger($name, [$handler]);
        // Add a custom log processor that escapes some problematic characters in the log record.
        $logger->pushProcessor([__CLASS__, 'escapeLogRecord']);

        // Use a UID processor for the RotatingFileHandler.
        // Unfortunately the service monolog.processor.uid is not public so we can't use the DI directly to get
        // the processor for the handler. Instead we get it from the pluginlogger service, that is accessible
        // via DI container.
        /** @var Logger $pluginLogger */
        $pluginLogger = $this->container->get('pluginlogger');
        $pluginLoggerHandlers = $pluginLogger->getHandlers();
        if (count($pluginLoggerHandlers) === 0) {
            return $logger;
        }
        // Unfortunately there is no getProcessors method, so we use a little work around here:
        // First pop out the processor (there should be only one registered in $pluginLoggerHandlers)
        try {
            $processor = $pluginLoggerHandlers[0]->popProcessor();
        } catch (\LogicException $e) {
            // Happens when for whatever reason there is no processor registered in the handler.
            return $logger;
        }
        // Since the processor has been removed with the pop, push it back immediately
        $pluginLoggerHandlers[0]->pushProcessor($processor);
        // Now there is a local reference to the processor needed and it is registered in the handler for the
        // logger.
        $handler->pushProcessor($processor);

        return $logger;
    }

    /**
     * Escapes log record.
     *
     * In the message, replaces every square bracket with a special unicode bracket.
     *
     * The parsing of the logs by the SW service Shopware\Components\Log\Parser\LogfileParser can be confused by
     * square brackets in the log message.
     *
     * @param array $record
     * @return array
     */
    public static function escapeLogRecord($record)
    {
        $record['message'] = strtr($record['message'], [
            '[' => mb_convert_encoding('&#x301A;', 'UTF-8', 'HTML-ENTITIES'),
            ']' => mb_convert_encoding('&#x301B;', 'UTF-8', 'HTML-ENTITIES'),
        ]);

        return $record;
    }
}
