<?php

/**
 * Lifestyle Webconsulting GmbH
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is private by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace LifeStyle\Tools\DbLogBundle\Logger;

use Doctrine\ORM\EntityManagerInterface;
use Monolog\Handler\AbstractProcessingHandler;
use LifeStyle\Tools\DbLogBundle\Entity\SystemLog;
use LifeStyle\Tools\DbLogBundle\Entity\SystemLogData;

/**
 * Class DatabaseHandler
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package    LifeStyle\Tools\DbLogBundle\Logger
 */
class DatabaseHandler extends AbstractProcessingHandler
{
    /**
     * Container
     *
     * @var \Symfony\Component\DependencyInjection\ContainerInterface
     */
    protected $container;

    /**
     *
     * @var EntityManagerInterface
     */
    private $entityManager;

    /**
     * Writer disabled
     *
     * @var bool
     */
    protected $disabled = false;

    /**
     * @param \Symfony\Component\DependencyInjection\ContainerAwareInterface $container
     */
    public function setContainer($container)
    {
        $this->container = $container;
    }

    /**
     * Enable/disable log-handler
     *
     * @param bool $enable
     */
    public function enable($enable = true)
    {
        $this->disable(!$enable);
    }

    /**
     * Disable/enable log-handler
     *
     * @param bool $disable
     */
    public function disable($disable = true)
    {
        $this->disabled = (bool)$disable;
    }

    /**
     * Check if log-handler is disabled
     * @return bool
     */
    public function isDisabled()
    {
        return $this->disabled;
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        // Check disabled, console and log level
        if ($this->isDisabled() || php_sapi_name() == 'cli' || $record['level'] < $this->level) {
            return;
        }

        $serverData = $record['extra']['serverData'];
        unset($record['extra']['serverData']);

        $username = isset($record['extra']['username']) ? $record['extra']['username'] : null;
        unset($record['extra']['username']);

        $extraLog = implode('|||', $record['extra']);

        // Disable temporary to prevent from infinite loops, if doctrine channel is enabled for logging
        $this->disable();

        try {
            $dataEntity = new SystemLogData();
            $dataEntity->setLog($record['message']);
            $dataEntity->setServerData($serverData);

            $entity = new SystemLog();
            $entity->setLevel($record['level']);
            $entity->setChannel($record['channel']);
            $entity->setExtras($extraLog);
            $entity->setSystemLogData($dataEntity);
            $entity->setUsername($username);

            $entityManager = $this->getEntityManager();
            $entityManager->persist($dataEntity);
            $entityManager->persist($entity);
            $entityManager->flush($dataEntity);
            $entityManager->flush($entity);
        } catch (\Exception $e) {

            // Fallback to just writing to php error logs if something really bad happens
            error_log($record['message']);
            error_log($e->getMessage());
        }
        $this->enable();
    }

    /**
     * @return EntityManagerInterface
     */
    private function getEntityManager()
    {
        return null !== $this->entityManager ? $this->entityManager : ($this->entityManager = $this->container->get('doctrine')->getManager('ReadWrite'));
    }
}
