<?php

/*
 * kohinos_cooperatic
 * Copyright (C) 2019-2020  ADML63
 * Copyright (C) 2020- Cooperatic
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace App\Factory;

use App\Entity\TransactionAdherentAdherent;
use App\Entity\TransactionAdherentPrestataire;
use App\Entity\TransactionComptoirAdherent;
use App\Entity\TransactionComptoirGroupe;
use App\Entity\TransactionComptoirPrestataire;
use App\Entity\TransactionPrestataireAdherent;
use App\Entity\TransactionPrestatairePrestataire;
use App\Entity\TransfertComptoirGroupe;
use App\Entity\TransfertGroupeComptoir;
use App\Entity\TransfertGroupeSiege;
use App\Entity\TransfertPrestataireComptoir;
use App\Entity\TransfertPrestataireSiege;
use App\Entity\TransfertSiegeGroupe;
use App\Entity\RetraitComptoirAdherent;
use App\Entity\RetraitComptoirPrestataire;
use App\Entity\VenteComptoirAdherent;
use App\Entity\VenteComptoirPrestataire;
use App\Entity\Siege;
use App\Entity\AchatMonnaieAdherent;
use App\Entity\AchatMonnaiePrestataire;
use App\Entity\User;
use App\Form\Type\AdherentInfosFormType;
use App\Form\Type\ComptoirInfosFormType;
use App\Form\Type\GroupeInfosFormType;
use App\Form\Type\GroupePrestataireInscriptionFormType;
use App\Form\Type\PrestataireInfosFormType;
use App\Form\Type\RegistrationFormType;
use App\Form\Type\TransactionAdherentAdherentFormType;
use App\Form\Type\TransactionAdherentPrestataireFormType;
use App\Form\Type\TransactionPrestataireAdherentFormType;
use App\Form\Type\TransactionPrestatairePrestataireFormType;
use App\Form\Type\TransfertComptoirGroupeFormType;
use App\Form\Type\TransfertGroupeComptoirFormType;
use App\Form\Type\TransfertGroupeSiegeFormType;
use App\Form\Type\TransfertPrestataireComptoirFormType;
use App\Form\Type\TransfertPrestataireSiegeFormType;
use App\Form\Type\TransfertSiegeGroupeFormType;
use App\Form\Type\RetraitComptoirAdherentFormType;
use App\Form\Type\RetraitComptoirPrestataireFormType;
use App\Form\Type\SoldeSiegeFormType;
use App\Form\Type\VenteComptoirAdherentFormType;
use App\Form\Type\VenteComptoirPrestataireFormType;
use App\Form\Type\AchatMonnaieAdherentFormType;
use App\Form\Type\AchatMonnaiePrestataireFormType;
use App\Form\Type\UserInfosFormType;
use Doctrine\ORM\EntityManagerInterface;
use FOS\UserBundle\Form\Type\ChangePasswordFormType;
use Symfony\Component\Form\FormFactoryInterface as FormF;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\RouterInterface;

class FormFactory
{
    private $ff;
    private $router;
    private $session;
    private $em;

    public function __construct(FormF $ff, RouterInterface $router, SessionInterface $session, EntityManagerInterface $em)
    {
        $this->ff = $ff;
        $this->router = $router;
        $this->session = $session;
        $this->em = $em;
    }

    public function getUserInfosForm(User $user)
    {
        if (empty($user)) {
            throw new \Exception("[FORM 0] Opération impossible !");
        }
        $form = $this->ff->create(UserInfosFormType::class, $user, array('action' => $this->router->generate('user_infos')));

        return $form->createView();
    }

    public function getUserPasswordForm(User $user)
    {
        if (empty($user)) {
            throw new \Exception("[FORM 1] Opération impossible !");
        }
        $form = $this->ff->create(ChangePasswordFormType::class, $user, array('action' => $this->router->generate('fos_user_change_password')));

        return $form->createView();
    }

    public function getGroupeInfosForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_groupegere'))) {
            throw new \Exception("[FORM 2] Opération impossible !");
        }
        $form = $this->ff->create(GroupeInfosFormType::class, $this->session->get('_groupegere'), array('action' => $this->router->generate('groupe_infos')));

        return $form->createView();
    }

    public function getComptoirInfosForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_comptoirgere'))) {
            throw new \Exception("[FORM 3] Opération impossible !");
        }
        $form = $this->ff->create(ComptoirInfosFormType::class, $this->session->get('_comptoirgere'), array('action' => $this->router->generate('comptoir_infos')));

        return $form->createView();
    }

    public function getPrestataireInfosForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_prestagere'))) {
            throw new \Exception("[FORM 4] Opération impossible !");
        }
        $form = $this->ff->create(PrestataireInfosFormType::class, $this->session->get('_prestagere'), array('action' => $this->router->generate('prestataire_infos')));

        return $form->createView();
    }

    public function getAdherentInfosForm(User $user)
    {
        if (empty($user) || empty($user->getAdherent())) {
            throw new \Exception("[FORM 5] Opération impossible !");
        }
        $form = $this->ff->create(AdherentInfosFormType::class, $user->getAdherent(), array('action' => $this->router->generate('adherent_infos')));

        return $form->createView();
    }

    public function getGroupePrestataireInscriptionForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_prestagere'))) {
            throw new \Exception("[FORM 6] Opération impossible !");
        }

        //#180: at this point, the Prestataire entity is detached from the EntityManager (because we get it from the session)
        $presta = $this->session->get('_prestagere');
        //#180: $presta now refers to the fully managed copy returned by the merge operation.
        $presta = $this->em->merge($presta);

        $form = $this->ff->create(GroupePrestataireInscriptionFormType::class, $presta, array('action' => $this->router->generate('groupeprestataire_inscription')));

        return $form->createView();
    }

    public function getTransactionAdherentAdherentForm(User $user)
    {
        if (empty($user) || empty($user->getAdherent())) {
            throw new \Exception("[FORM 7] Opération impossible !");
        }
        $entity = new TransactionAdherentAdherent();
        $entity->setOperateur($user);
        $entity->setExpediteur($user->getAdherent());
        $form = $this->ff->create(TransactionAdherentAdherentFormType::class, $entity, array('action' => $this->router->generate('transactionAdherentAdherent')));

        return $form->createView();
    }

    public function getTransactionAdherentPrestataireForm(User $user)
    {
        if (empty($user) || empty($user->getAdherent())) {
            throw new \Exception("[FORM 8] Opération impossible !");
        }
        $entity = new TransactionAdherentPrestataire();
        $entity->setOperateur($user);
        $entity->setExpediteur($user->getAdherent());
        $form = $this->ff->create(TransactionAdherentPrestataireFormType::class, $entity, array('action' => $this->router->generate('transactionAdherentPrestataire')));

        return $form->createView();
    }

    public function getTransactionPrestataireAdherentForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_prestagere'))) {
            throw new \Exception("[FORM] Opération impossible !");
        }
        $entity = new TransactionPrestataireAdherent();
        $entity->setOperateur($user);
        $entity->setExpediteur($this->session->get('_prestagere'));
        $form = $this->ff->create(TransactionPrestataireAdherentFormType::class, $entity, array('action' => $this->router->generate('transactionPrestataireAdherent')));

        return $form->createView();
    }

    public function getTransactionPrestatairePrestataireForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_prestagere'))) {
            throw new \Exception("[FORM 9] Opération impossible !");
        }
        $entity = new TransactionPrestatairePrestataire();
        $entity->setOperateur($user);
        $entity->setExpediteur($this->session->get('_prestagere'));
        $form = $this->ff->create(TransactionPrestatairePrestataireFormType::class, $entity, array('action' => $this->router->generate('transactionPrestatairePrestataire')));

        return $form->createView();
    }

    public function getTransfertPrestataireSiegeForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_prestagere'))) {
            throw new \Exception("[FORM 10] Opération impossible !");
        }
        $entity = new TransfertPrestataireSiege();
        $entity->setExpediteur($this->session->get('_prestagere'));
        $form = $this->ff->create(TransfertPrestataireSiegeFormType::class, $entity, array('action' => $this->router->generate('transactionPrestataireSiege')));

        return $form->createView();
    }

    public function getTransfertPrestataireComptoirForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_comptoirgere'))) {
            throw new \Exception("[FORM 11] Opération impossible !");
        }
        $entity = new TransfertPrestataireComptoir();
        $entity->setDestinataire($this->session->get('_comptoirgere'));
        $form = $this->ff->create(TransfertPrestataireComptoirFormType::class, $entity, array('action' => $this->router->generate('transfertPrestataireComptoir')));

        return $form->createView();
    }

    public function getRetraitComptoirToXForm(User $user, $type)
    {
        $type = strtolower($type);
        if (empty($user) || empty($this->session->get('_comptoirgere')) || !($type == 'adherent' || $type == 'groupe' || $type == 'prestataire')) {
            throw new \Exception("[FORM 12] Opération impossible !");
        }
        $class = "App\Entity\RetraitComptoir" . ucwords($type);
        $entity = new $class();
        $entity->setOperateur($user);
        $entity->setExpediteur($this->session->get('_comptoirgere'));
        $form = $this->ff->create('App\Form\Type\RetraitComptoir' . ucwords($type) . 'FormType', $entity, array('action' => $this->router->generate('retraitComptoir' . ucwords($type))));

        return $form->createView();
    }

    public function getVenteComptoirToXForm(User $user, $type)
    {
        $type = strtolower($type);
        if (empty($user) || empty($this->session->get('_comptoirgere')) || !($type == 'adherent' || $type == 'groupe' || $type == 'prestataire')) {
            throw new \Exception("[FORM 12] Opération impossible !");
        }
        $class = "App\Entity\VenteComptoir" . ucwords($type);
        $entity = new $class();
        $entity->setOperateur($user);
        $entity->setExpediteur($this->session->get('_comptoirgere'));
        $form = $this->ff->create('App\Form\Type\VenteComptoir' . ucwords($type) . 'FormType', $entity, array('action' => $this->router->generate('venteComptoir' . ucwords($type))));

        return $form->createView();
    }

    public function getTransfertComptoirGroupeForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_groupegere'))) {
            throw new \Exception("[FORM 12] Opération impossible !");
        }
        $entity = new TransfertComptoirGroupe();
        $entity->setOperateur($user);
        $entity->setDestinataire($this->session->get('_groupegere'));
        $form = $this->ff->create(TransfertComptoirGroupeFormType::class, $entity, array('action' => $this->router->generate('transfertComptoirGroupe')));

        return $form->createView();
    }

    public function getTransfertGroupeComptoirForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_groupegere'))) {
            throw new \Exception("[FORM 13] Opération impossible !");
        }
        $entity = new TransfertGroupeComptoir();
        $entity->setOperateur($user);
        $entity->setExpediteur($this->session->get('_groupegere'));
        $form = $this->ff->create(TransfertGroupeComptoirFormType::class, $entity, array('action' => $this->router->generate('transfertGroupeComptoir')));

        return $form->createView();
    }

    public function getTransfertSiegeGroupeForm(User $user)
    {
        if (empty($user) || !$user->hasRole('ROLE_ADMIN_SIEGE')) {
            throw new \Exception("[FORM 14] Opération impossible !");
        }
        $entity = new TransfertSiegeGroupe();
        $entity->setOperateur($user);
        $form = $this->ff->create(TransfertSiegeGroupeFormType::class, $entity, array('action' => $this->router->generate('transfertSiegeGroupe')));

        return $form->createView();
    }

    public function getTransfertGroupeSiegeForm(User $user)
    {
        if (empty($user) || !$user->hasRole('ROLE_ADMIN_SIEGE')) {
            throw new \Exception("[FORM 15] Opération impossible !");
        }
        $entity = new TransfertGroupeSiege();
        $entity->setOperateur($user);
        $form = $this->ff->create(TransfertGroupeSiegeFormType::class, $entity, array('action' => $this->router->generate('transfertGroupeSiege')));

        return $form->createView();
    }

    public function getSoldeSiegeForm(User $user)
    {
        if (empty($user) || false === ($user->hasRole('ROLE_ADMIN_SIEGE') || $user->hasRole('ROLE_TRESORIER'))) {
            throw new \Exception("[FORM 16] Opération impossible !");
        }
        $siege = $this->em->getRepository(Siege::class)->findOneById(1);
        $form = $this->ff->create(SoldeSiegeFormType::class, $siege, array('action' => $this->router->generate('soldeSiege')));

        return $form->createView();
    }

    public function getAchatMonnaieAdherentForm(User $user)
    {
        if (empty($user) || empty($user->getAdherent())) {
            throw new \Exception("[FORM 16] Opération impossible !");
        }
        $entity = new AchatMonnaieAdherent();
        $entity->setOperateur($user);
        $form = $this->ff->create(AchatMonnaieAdherentFormType::class, $entity, array('action' => $this->router->generate('achatMonnaieAdherent')));

        return $form->createView();
    }

    public function getAchatMonnaiePrestataireForm(User $user)
    {
        if (empty($user) || empty($this->session->get('_prestagere'))) {
            throw new \Exception("[FORM 17] Opération impossible !");
        }
        $entity = new AchatMonnaiePrestataire();
        $entity->setOperateur($user);
        $form = $this->ff->create(AchatMonnaiePrestataireFormType::class, $entity, array('action' => $this->router->generate('achatMonnaiePrestataire')));

        return $form->createView();
    }
}
