<?php

/**
 * Webservice controller
 *
 * 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  2014 Lifestyle Webconsulting GmbH
 * @version    $Id:$
 * @link       http://www.life-style.de
 */

namespace Sso\WebserviceBundle\Controller;

use Sso\WebserviceBundle\Api;
use Sso\WebserviceBundle\ServiceCommand;
use Sso\WebserviceBundle\ServiceRequest;
use Sso\WebserviceBundle\Services\CommandHandlerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Sso\WebserviceBundle\Api\Exception\Type\Api as ApiException;
use Sso\WebserviceBundle\Api\Response\Builder as XmlResponse;
use JMS\DiExtraBundle\Annotation as DI;
use JMS\SecurityExtraBundle\Annotation\Secure;

/**
 * Webservice controller class
 */
class WebserviceController extends Controller
{

    /**
     * Api controller name
     * @var string
     */
    private $apiControllerName = 'Unknown';

    /**
     * Api controller action
     * @var string
     */
    private $apiActionName = 'Unknown';

    /**
     * @var integer
     */
    private $apiVersion = 1;

    /**
     * @var Api\Error\Storage
     */
    private $errors;

    /**
     * @var XmlResponse
     */
    private $xmlResponse;

    /**
     * @DI\Inject("webservice.services.command_handler")
     * @var CommandHandlerInterface
     */
    private $commandHandler;

    /**
     * @DI\Inject("webservice.service_command")
     * @var ServiceCommand
     */
    private $serviceCommand;

    /**
     * @var array
     */
    private $version2 = [
        'ApplicationAll',
        'ApplicationAttributeAdd',
        'ApplicationAttributeShow',
        'UserAdd',
        'UserShow',
        'UserUpdate',
        'UserApplicationShow',
        'UserApplicationDelete',
        'UserApplicationShowDetails',
        'UserApplicationAttributeAdd',
        'UserApplicationAttributeShow',
        'UserApplicationRoleShow',
        'UserSearchFindByApplication',
        'UserSearchFindByApplicationAttribute',
        'UserSearchFindByApplicationRole',
        'UserSearchAdvanced',
        'UserChangePassword',
        'UserResetPassword',
        'UserGroupAdd',
        'UserGroupSearch',
        'UserGroupUpdate',
        'UserGroupDelete',
        'PasswordPolicyShow',
    ];

    /**
     * @var array
     */
    private $version3 = [
        'ApplicationAll',
        'UserUpdate',
        'UserAdd',
        'UserShow',
        'UserApplicationShowDetails',
        'UserChangePassword',
        'PasswordPolicyShow',
        'UserSearchAdvanced',
    ];

    private $version4 = [
        'UserUpdate',
        'UserAdd',
        'UserShow',
    ];

    private $version5 = [
        'UserUpdate',
        'UserShow',
    ];

    /**
     * Webservice default action
     * @Secure(roles="ROLE_WEBSERVICE")
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function indexAction(Request $request)
    {
        $this->getUser();
        // Set logger
        Api\Error\Type\Base::$log = $this->apiM()->logger();

        //set data
        $this->apiVersion = $this->serviceCommand->getApiVersion();
        $this->apiControllerName = $this->serviceCommand->getController();
        $this->apiActionName = $this->serviceCommand->getAction();
        $versionAvailable = $this->apiControllerName.$this->apiActionName;

        // Handle requests with api-version >= 2
        $versionVarName = 'version' . $this->apiVersion;
        if(isset($this->$versionVarName) && in_array($versionAvailable, $this->$versionVarName)){
            $responseBuilder = $this->commandHandler->handle(
                $this->serviceCommand,
                ServiceRequest::createFromRequest($request)
            );

            $response = new Response();
            $response->headers->set('Content-type', 'text/xml');
            $response->setContent($responseBuilder->build('xml'));

            return $response;
        }

        // Retrieve body from php input
        $xmlRequest = $this->get('request')->getContent();
        // Create xml response document
        $xmlResponse = $this->response();

        // Execute controller action and output xml-response
        $controller = $this->apiM()->controller()->getController($this->apiControllerName, $this->apiActionName, $xmlRequest, $xmlResponse);
        $controller->callAction($this->apiActionName);

        // Output
        $response = new Response();
        $response->headers->set('Content-type', 'text/xml');
        $response->setContent($xmlResponse->output());
        return $response;
    }

    /**
     * Get response container
     * @return XmlResponse
     */
    private function response()
    {
        return null !== $this->xmlResponse ? $this->xmlResponse : ($this->xmlResponse = new XmlResponse());
    }

    /**
     * Exit with error
     * Send error xml
     * @param Api\Error\Type\Base $error
     * @throws ApiException
     */
    private function _exitResponse(Api\Error\Type\Base $error = null)
    {
        if (null !== $error) {
            $this->errors()->addError($error);
        }
        $exc = new ApiException();
        $exc->setErrors($this->errors()->getErrors());
        throw $exc;
    }

    /**
     * Error storage
     * @return Api\Error\Storage
     */
    public function errors()
    {
        return null !== $this->errors ? $this->errors : ($this->errors = new Api\Error\Storage());
    }

    /**
     * Api Manager
     * @return Api\Manager
     */
    private function apiM()
    {
        return $this->get('service_api_manager');
    }
}
