<?php

/**
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is protected 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
 * @version    $Id:$
 * @link       http://www.life-style.de
 */

namespace Sso\ApiBundle\Api\Error\Type;

use Psr\Log\LogLevel;

/**
 * Error base class
 *
 * Every error shoud inherit this class
 *
 * @property-read string $code Error-code
 * @property-read string $shortMessage short version of error message
 * @property-read string $longMessage long version of error message, more detailed
 */
abstract class Base
{

    /**
     * Logger
     *
     * @var \Sso\ApiBundle\Api\Logger\Index
     */
    public static $log;

    /**
     * Error counter
     *
     * @var int
     */
    private $_errorCount = 1;

    /**
     * Error code
     *
     * @var string
     */
    protected $_errorCode;

    /**
     * Error reference - unique string, to find error in code
     *
     * @var string
     */
    protected $_errorRef;

    /**
     * Errors short message
     *
     * @var string
     */
    protected $_shortMessage;

    /**
     * Errors long message
     *
     * @var string
     */
    protected $_longMessage;

    /**
     * Constructor
     *
     * @param string $errorRef
     * @param string $errorCode
     * @param string $shortMessage
     * @param string $longMessage
     */
    public function __construct($errorRef, $errorCode = '', $shortMessage = '', $longMessage = '')
    {
        $this->codeToMessage($errorCode, $shortMessage, $longMessage);
        $this->_errorCode = (string)$errorCode;
        $this->_errorRef = (string)$errorRef;
        $this->_shortMessage = (string)$shortMessage;
        $this->_longMessage = (string)$longMessage;
        $this->_log();
    }

    /**
     * Magic getter
     *
     * @param string $name
     * @return string
     */
    public function __get($name)
    {
        switch (strtolower($name)) {
            case 'code':
                return $this->_errorCode;
            case 'ref':
                return $this->_errorRef;
            case 'shortmessage':
                return $this->_shortMessage;
            case 'longmessage':
                return $this->_longMessage;
        }
        return '';
    }

    /**
     * Unique identifier for error
     *
     * @return string
     */
    public function getIdentifier()
    {
        return md5($this->_errorCode . $this->_shortMessage . $this->_longMessage);
    }

    /**
     * Indicator how often same error has occured
     *
     * @return int
     */
    public function getErrorCount()
    {
        return $this->_errorCount;
    }

    /**
     * Increase error counter
     *
     * @param int $count
     */
    public function incErrorCount($count = 1)
    {
        $this->_errorCount += $count;
    }

    /**
     * Get error priority
     *
     * @see \Psr\Log\LogLevel\LogLevel
     * @return int
     */
    protected function _getLogPriority()
    {
        return LogLevel::ERROR;
    }

    /**
     * Get log message
     *
     * @return string
     */
    protected function _getLogMessage()
    {
        return ucfirst($this->getErrorType()) . ' error [' . $this->_errorCode . ']: ' . $this->_shortMessage . ' (' . $this->_longMessage . ')';
    }

    /**
     * Log error
     */
    protected function _log()
    {
        if (self::$log) {
            self::$log->log($this->_getLogMessage(), $this->_getLogPriority());
        }
    }

    /**
     * String representation of error
     *
     * @return string
     */
    public function __toString()
    {
        return $this->_errorCode . ': ' . $this->_shortMessage . ' ' . $this->_longMessage;
    }

    /**
     * Get type of this error
     *
     * Default error type ist 'external'
     *
     * @return string
     */
    abstract public function getErrorType();

    /**
     *
     * @param string $errorCode
     * @param string $shortMessage
     * @param string $longMessage
     */
    abstract protected function codeToMessage(&$errorCode, &$shortMessage, &$longMessage);
}
