<?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 Sso\WebserviceBundle\ErrorHandler\ErrorStorage;

use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Sso\WebserviceBundle\ErrorHandler\ErrorStorage\Error as StoredError;
use Throwable;

/**
 * Class Factory
 *
 * @copyright  2016 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package    Sso\WebserviceBundle\ErrorHandler\ErrorStorage
 */
final class Factory
{
    /**
     * @var array
     */
    private $setter;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * Factory constructor.
     * @param LoggerInterface $logger
     */
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @return Errors
     */
    public function errors()
    {
        //we always need the same instance here!
        return isset($this->setter[__METHOD__]) ? $this->setter[__METHOD__] : ($this->setter[__METHOD__] = new Errors());
    }

    /**
     * @param string $controller
     */
    public function setController($controller){
        $this->errors()->setController($controller);
    }

    /**
     * @param string $action
     */
    public function setAction($action){
        $this->errors()->setAction($action);
    }

    /**
     * @return Errors
     */
    public function getStoredErrors(){
        return $this->errors();
    }

    /**
     * @return Error
     */
    public function error(){
        //we always need a fresh instance here!
        return new Error();
    }

    /**
     * @return bool
     */
    public function hasErrors(){

        return $this->errors()->hasErrors();
    }


    /**
     * @param array $errors
     */
    public function setErrorFromArray(array $errors){

        $singleError = $this->error()->setFromArray($errors);
        $this->errors()->addError($singleError);
        $this->logAndTraceError($singleError);
    }

    /**
     * @param integer $code
     * @param string $errorCode
     * @param string $errorRef
     * @param string $shortMessage
     * @param string $longMessage
     * @param Throwable|null $exception
     */
    public function setErrorFromValues($code, $errorCode, $errorRef, $shortMessage, $longMessage, Throwable $exception = null)
    {
        $singleError = $this->error()->setErrorFromValues($code, $errorCode, $errorRef, $shortMessage, $longMessage, $exception);
        $this->errors()->addError($singleError);
        $this->logAndTraceError($singleError);
    }

    /**
     * @param Error $singleError
     */
    private function logAndTraceError(StoredError $singleError)
    {
        $logString = '';

        if (function_exists('debug_backtrace')) {

            $trace = debug_backtrace();
            $caller = isset($trace[3]) ? $trace[3] : false;
            if($caller){
                if(isset($caller['class'])){
                    $logString .= 'Called from: '.$caller['class'];
                }

                if(isset($caller['function'])){
                    $logString .= '::'.$caller['function'];
                }

                if(isset($caller['line'])){
                    $logString .= '::'.$caller['line'].' - ';
                }
            }
        }

        $logString .= $singleError->getShortMessage().' '.$singleError->getLongMessage();
        $this->logger->error((string)$logString);
    }
}
