<?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 Sso\WebserviceBundle\Api\Exception\Type\Api as ApiException;
use Throwable;

/**
 * Class Error
 * @package Sso\WebserviceBundle\ErrorHandler\ErrorStorage
 */
final class Error
{
    use ErrorCodeTranslator;

    /**
     * @var integer
     */
    private $code;

    /**
     * @var string
     */
    private $status;

    /**
     * @var string
     */
    private $trackId;

    /**
     * @var string
     */
    private $type;

    /**
     * @var Throwable|null
     */
    private $exception;

    /**
     * @var string
     */
    private $debug;

    /**
     * @var string
     */
    private $errorCode;

    /**
     * @var string
     */
    private $errorRef;

    /**
     * @var string
     */
    private $shortMessage;

    /**
     * @var string
     */
    private $longMessage;

    /**
     * @var array
     */
    private $codeToStatus;

    /**
     * Error constructor.
     */
    public function __construct()
    {
        $this->trackId = ApiException::getTrackId();
        $this->codeToStatus =   [   200 => 'OK',
                                    400 => 'Bad Request',
                                    401 => 'Unauthorized',
                                    403 => 'Forbidden',
                                    404 => 'Not Found',
                                    406 => 'Not Acceptable',
                                    500 => 'Internal Server Error'
                                ];
    }

    /**
     * @param array $errorAttributes
     * @return Error
     */
    public function setFromArray(array $errorAttributes)
    {
        foreach ($errorAttributes as $name => $value) {
            $method = 'set' . ucfirst($name);
            if (!method_exists($this, $method)) {
                throw new \BadMethodCallException(sprintf(
                    'Unable to create error response model %s! Errorattribute %s does not exist.',
                    self::class,
                    $name
                ));
            }
            $this->$method($value);
        }
        return $this;
    }

    /**
     * @param integer $code
     * @param string $errorCode
     * @param string $errorRef
     * @param string $shortMessage
     * @param string $longMessage
     * @param Throwable $exception
     *
     * @return Error
     */
    public function setErrorFromValues($code, $errorCode, $errorRef, $shortMessage, $longMessage, Throwable $exception = null){
        $this->codeToMessage($errorCode, $shortMessage, $longMessage);
        $this->setCode($code);
        $this->setErrorCode($errorCode);
        $this->setErrorRef($errorRef);
        $this->setShortMessage($shortMessage);
        $this->setLongMessage($longMessage);
        $this->setException($exception);

        return $this;
    }

    /**
     * @return int
     */
    public function getCode()
    {
        return $this->code;
    }

    /**
     * @param int $code
     * @return Error
     */
    public function setCode($code)
    {
        $this->code = $code;

        //status depends on code so set it
        if(array_key_exists($code, $this->codeToStatus)){
            $this->status = $this->codeToStatus[$code];
        } else {
            $this->status =  $this->codeToStatus[500];
            $this->code = 500;
        }

        // type depends on code so set it
        if($this->code === 500){
            $this->type = 'Internal Error';
        } else {
            $this->type = 'External Error';
        }

        return $this;
    }

    /**
     * @return string
     */
    public function getStatus()
    {
        return $this->status;
    }

    /**
     * @return string
     */
    public function getTrackId()
    {
        return $this->trackId;
    }

    /**
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * @param string $type
     * @return Error
     */
    public function setType($type)
    {
        $this->type = $type;

        return $this;
    }

    /**
     * @return Throwable|null
     */
    public function getException()
    {
        return $this->exception;
    }

    /**
     * @param Throwable $exception
     * @return Error
     */
    public function setException($exception)
    {
        $this->exception = $exception;

        return $this;
    }

    /**
     * @return string
     */
    public function getDebug()
    {
        return $this->debug;
    }

    /**
     * @param string $debug
     * @return Error
     */
    public function setDebug($debug)
    {
        $this->debug = $debug;

        return $this;
    }

    /**
     * @return string
     */
    public function getErrorCode()
    {
        return $this->errorCode;
    }

    /**
     * @param string $errorCode
     * @return Error
     */
    public function setErrorCode($errorCode)
    {
        $this->errorCode = $errorCode;

        return $this;
    }

    /**
     * @return string
     */
    public function getErrorRef()
    {
        return $this->errorRef;
    }

    /**
     * @param string $errorRef
     * @return Error
     */
    public function setErrorRef($errorRef)
    {
        $this->errorRef = $errorRef;

        return $this;
    }

    /**
     * @return string
     */
    public function getShortMessage()
    {
        return $this->shortMessage;
    }

    /**
     * @param string $shortMessage
     * @return Error
     */
    public function setShortMessage($shortMessage)
    {
        $this->shortMessage = $shortMessage;

        return $this;
    }

    /**
     * @return string
     */
    public function getLongMessage()
    {
        return $this->longMessage;
    }

    /**
     * @param string $longMessage
     * @return Error
     */
    public function setLongMessage($longMessage)
    {
        $this->longMessage = $longMessage;

        return $this;
    }
}
