<?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\BackendBundle\Controller;

use Doctrine\ORM\EntityManager;
use Sso\BackendBundle\Model\Form\PasswordPolicyTranslations;
use Sso\WebserviceBundle\Entity\Webservice\Type\PasswordPolicyValidations;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Sso\BackendBundle\Form;
use Sso\WebserviceBundle\Entity\Webservice\Type\PasswordPolicy;
use Sso\BackendBundle\Model\Form\PasswordPolicy as PolicyForm;
use JMS\DiExtraBundle\Annotation\Inject;
use Sso\WebserviceBundle\Database\Manager as DbManager;

/**
 * Class PasswordPolicyController
 * @package Sso\BackendBundle\Controller
 */
class PasswordPolicyController extends Controller
{
    /**
     * @Inject("service_database_manager")
     * @var DbManager
     */
    private $dbM;

    /**
     * @Route("/", name="_admin_backend_passwordpolicy_list")
     * @Template()
     *
     * @param Request $request
     * @return array
     */
    public function listAction(Request $request)
    {
        // initialize a query builder
        $em = $this->get('doctrine.orm.webservice_entity_manager');
        $filterBuilder = $em
            ->getRepository('SsoWebserviceBundle:Type\PasswordPolicy')
            ->createQueryBuilder('a');

        $form = $this->get('form.factory')->create(Form\PasswordPoliciesFilterType::class);
        $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder);

        $query = $filterBuilder->getQuery();
        $paginator = $this->get('knp_paginator');
        $pagination = $paginator->paginate($query, $request->query->get('page', 1), 50);

        return ['form' => $form->createView(), 'pagination' => $pagination];
    }

    /**
     * @Route("/", name="_admin_backend_passwordpolicy_add")
     * @Template()
     *
     * @param Request $request
     * @return array|RedirectResponse
     */
    public function addAction(Request $request)
    {
        $em = $this->get('doctrine.orm.webservice_entity_manager');

        $form = $this->get('form.factory')->create(
            Form\PasswordPoliciesType::class,
            null,
            ['method' => 'POST']
        );

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            /** @var PolicyForm $formData */
            $formData = $form->getData();

            if ($formData->isDefault() == '1') {
                $this->dbM->webservice()->passwordPolicy()->clearDefault();
            }

            $policy = new PasswordPolicy();
            $policy
                ->setRegEx($formData->getRegEx())
                ->setTitle($formData->getTitle())
                ->setValidityDuration($formData->getValidityDuration())
                ->setHistorySize($formData->getHistorySize())
                ->setEditDistance($formData->getEditDistance())
                ->setChangeDelay($formData->getChangeDelay())
                ->setPolicyDescription($formData->getPolicyDescription())
                ->setDefault($formData->isDefault() == '1');

            //add error messages
            $passwordPolicyOrderId = 0;
            foreach ($formData->getPasswordPolicyValidations() as $validation) {
                if (0 === strlen($validation->getRegEx())) {
                    continue;
                }
                $passwordPolicyValidation = new PasswordPolicyValidations();
                $passwordPolicyValidation->setRegEx($validation->getRegEx());
                $passwordPolicyValidation->setOrderId(++$passwordPolicyOrderId);
                $passwordPolicyValidation->setErrorMessages($this->formDataToArray($validation->getErrorMessages()));
                $passwordPolicyValidation->setHintMessages($this->formDataToArray($validation->getHintMessages()));
                $policy->addPasswordPolicyValidation($passwordPolicyValidation);
                $em->persist($passwordPolicyValidation);
            }

            $policy->setErrorMessages($this->formDataToArray($formData->getErrorMessages()));
            $policy->setRegexErrorMessages($this->formDataToArray($formData->getRegexErrorMessages()));
            $policy->setValidityDurationErrorMessages($this->formDataToArray($formData->getValidityDurationErrorMessages()));
            $policy->setHistorySizeErrorMessages($this->formDataToArray($formData->getHistorySizeErrorMessages()));
            $policy->setEditDistanceErrorMessages($this->formDataToArray($formData->getEditDistanceErrorMessages()));
            $policy->setChangeDelayErrorMessages($this->formDataToArray($formData->getChangeDelayErrorMessages()));

            $em->persist($policy);
            $em->flush();

            return $this->redirect($this->generateUrl('_admin_backend_passwordpolicy_list', []));
        }

        return [
            'form' => $form
        ];
    }

    /**
     * @Route("/", name="_admin_backend_passwordpolicy_delete")
     * @Template()
     *
     * @param Request $request
     * @return array|RedirectResponse
     */
    public function deleteAction(Request $request, $policyId)
    {
        $em = $this->get('doctrine.orm.webservice_entity_manager');
        /** @var PasswordPolicy $policy */
        $policy = $this->dbM->webservice()->passwordPolicy()->getOne(
            [
                'policyId' => $policyId
            ]
        );

        if ($policy === null) {
            $this->addFlash('error', 'Policy not found!');
            return $this->redirect($this->generateUrl('_admin_backend_passwordpolicy_list', []));
        }

        if ($request->query->get('exec') == '1') {
            $em->remove($policy);
            $em->flush();
            return $this->redirect($this->generateUrl('_admin_backend_passwordpolicy_list', []));
        }

        return [
            'policy' => $policy
        ];
    }

    /**
     * @Route("/", name="_admin_backend_passwordpolicy_show")
     * @Template()
     *
     * @param Request $request
     * @return array|RedirectResponse
     */
    public function showAction(Request $request, $policyId)
    {
        /** @var PasswordPolicy $policy */
        $policy = $this->dbM->webservice()->passwordPolicy()->getOne(
            [
                'policyId' => $policyId
            ]
        );

        if ($policy === null) {
            $this->addFlash('error', 'Policy not found!');
            return $this->redirect($this->generateUrl('_admin_backend_passwordpolicy_list', []));
        }

        return [
            'policy' => $policy
        ];
    }

    /**
     * @Route("/", name="_admin_backend_passwordpolicy_edit")
     * @Template()
     *
     * @param Request $request
     * @return array|RedirectResponse
     */
    public function editAction(Request $request, $policyId)
    {
        /** @var EntityManager $em */
        $em = $this->get('doctrine.orm.webservice_entity_manager');
        /** @var PasswordPolicy $policy */
        $policy = $this->dbM->webservice()->passwordPolicy()->getOne(['policyId' => $policyId]);
        if (null === $policy) {
            $this->addFlash('error', 'Policy not found!');
            return $this->redirect($this->generateUrl('_admin_backend_passwordpolicy_list', []));
        }

        $policyData = new PolicyForm();
        $policyData
            ->setRegEx($policy->getRegEx())
            ->setTitle($policy->getTitle())
            ->setValidityDuration($policy->getValidityDuration())
            ->setHistorySize($policy->getHistorySize())
            ->setEditDistance($policy->getEditDistance())
            ->setChangeDelay($policy->getChangeDelay())
            ->setPolicyDescription($policy->getPolicyDescription())
            ->setDefault($policy->isDefault());

        foreach ($policy->getPasswordPolicyValidations() as $validation) {
            $passwordPolicyValidation = new \Sso\BackendBundle\Model\Form\PasswordPolicyValidations();
            $passwordPolicyValidation->setRegEx($validation->getRegEx());
            $passwordPolicyValidation->setErrorMessages($this->arrayToFormData($validation->getErrorMessages()));
            $passwordPolicyValidation->setHintMessages($this->arrayToFormData($validation->getHintMessages()));
            $policyData->addPasswordPolicyValidation($passwordPolicyValidation);
        }

        $policyData->setErrorMessages($this->arrayToFormData($policy->getErrorMessages()));
        $policyData->setRegexErrorMessages($this->arrayToFormData($policy->getRegexErrorMessages()));
        $policyData->setValidityDurationErrorMessages($this->arrayToFormData($policy->getValidityDurationErrorMessages()));
        $policyData->setHistorySizeErrorMessages($this->arrayToFormData($policy->getHistorySizeErrorMessages()));
        $policyData->setEditDistanceErrorMessages($this->arrayToFormData($policy->getEditDistanceErrorMessages()));
        $policyData->setChangeDelayErrorMessages($this->arrayToFormData($policy->getChangeDelayErrorMessages()));

        $form = $this->get('form.factory')->create(
            Form\PasswordPoliciesType::class,
            $policyData,
            ['method' => 'POST']
        );

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            /** @var PolicyForm $formData */
            $formData = $form->getData();

            if ($formData->isDefault()) {
                $this->dbM->webservice()->passwordPolicy()->clearDefaultExcludeId($policyId);
            }

            $policy
                ->setRegEx($formData->getRegEx())
                ->setTitle($formData->getTitle())
                ->setValidityDuration($formData->getValidityDuration())
                ->setHistorySize($formData->getHistorySize())
                ->setEditDistance($formData->getEditDistance())
                ->setChangeDelay($formData->getChangeDelay())
                ->setPolicyDescription($formData->getPolicyDescription())
                ->setDefault($formData->isDefault());

            foreach ($policy->getPasswordPolicyValidations() as $validation) {
                $em->remove($validation);
            }
            $policy->setPasswordPolicyValidations([]);
            $passwordPolicyOrderId = 0;
            foreach ($formData->getPasswordPolicyValidations() as $validation) {
                if (0 === strlen($validation->getRegEx())) {
                    continue;
                }
                $passwordPolicyValidation = new PasswordPolicyValidations();
                $passwordPolicyValidation->setRegEx($validation->getRegEx());
                $passwordPolicyValidation->setOrderId(++$passwordPolicyOrderId);
                $passwordPolicyValidation->setErrorMessages($this->formDataToArray($validation->getErrorMessages()));
                $passwordPolicyValidation->setHintMessages($this->formDataToArray($validation->getHintMessages()));
                $policy->addPasswordPolicyValidation($passwordPolicyValidation);
                $em->persist($passwordPolicyValidation);
            }

            $policy->setErrorMessages($this->formDataToArray($formData->getErrorMessages()));
            $policy->setRegexErrorMessages($this->formDataToArray($formData->getRegexErrorMessages()));
            $policy->setValidityDurationErrorMessages($this->formDataToArray($formData->getValidityDurationErrorMessages()));
            $policy->setHistorySizeErrorMessages($this->formDataToArray($formData->getHistorySizeErrorMessages()));
            $policy->setEditDistanceErrorMessages($this->formDataToArray($formData->getEditDistanceErrorMessages()));
            $policy->setChangeDelayErrorMessages($this->formDataToArray($formData->getChangeDelayErrorMessages()));

            $em->persist($policy);
            $em->flush();

            return $this->redirect($this->generateUrl('_admin_backend_passwordpolicy_list', []));
        }

        return [
            'form' => $form
        ];
    }

    /**
     * @param array $inputArray
     * @return array
     */
    private function formDataToArray($inputArray)
    {
        $resultArray = array();
        foreach ($inputArray as $item) {

            if (!empty($item->getLanguage()) && !empty($item->getMessage())) {
                /**
                 * @var PasswordPolicyTranslations $item
                 */
                $resultArray[$item->getLanguage()] = $item->getMessage();
            }

        }
        return $resultArray;
    }

    /**
     * @param array $inputArray
     * @return PasswordPolicyTranslations[]
     */
    private function arrayToFormData($inputArray)
    {
        if (empty($inputArray)) {
            return array();
        }

        $resultArray = array();
        foreach ($inputArray as $lang => $message) {
            $item = new PasswordPolicyTranslations();
            $item->setLanguage($lang);
            $item->setMessage($message);
            $resultArray[] = $item;
        }

        return $resultArray;
    }
}
