<?php
/**
 * @author Colinet Julien
 */

namespace CpCreation\VitiCore\Bridge\Doctrine\EventSubscriber;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Service\SherlockService;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Service\Uploader\FileUploader;
use CpCreation\VitiCore\Cart\Model\PaymentMethod;
use CpCreation\VitiCore\Cart\Model\Translation\PaymentMethodTranslation;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Events;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;

class PaymentMethodSubscriber implements EventSubscriber
{

    /**
     * @var Filesystem
     */
    private $filesystem;

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

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

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

    /**
     * @var FileUploader
     */
    private $uploader;

    private $paths;

    private $request;

    private $router;

    private $sherlockFinder;


    public function __construct(Filesystem $filesystem,
        FileUploader $uploader,
        $paths,
        SherlockService $fileFinder,
        RequestStack $requestStack,
        RouterInterface $router
    ) {
        $this->uploader       = $uploader;
        $this->filesystem     = $filesystem;
        $this->request        = $requestStack;
        $this->router         = $router;
        $this->sherlockFinder = $fileFinder;
        foreach ($paths as $key => $path) {
            if ($path['name'] === 'sherlock') {
                $this->paths[$key] = $path;
            }
        }
        $this->findFiles();
    }

    public function getSubscribedEvents()
    {
        return [
            Events::postPersist,
            Events::postUpdate,
            Events::postRemove,
        ];
    }

    /**
     * @param LifecycleEventArgs $args
     * @throws \Exception
     */
    public function postPersist(LifecycleEventArgs $args)
    {
        $entity        = $args->getEntity();
        $entityManager = $args->getEntityManager();
        if ($entity instanceof PaymentMethod && $entity->getMethod() == "sherlock") {
            $autoResponseUrl = $this->request->getCurrentRequest()->getUriForPath($this->router->generate($this->paths['sherlock']['response_at'], [], true));
            $returnUrl       = $this->request->getCurrentRequest()->getUriForPath($this->router->generate($this->paths['sherlock']['done'], [], true));
            $cancelUrl       = $this->request->getCurrentRequest()->getUriForPath($this->router->generate($this->paths['sherlock']['refused'], [], true));
            $sherlock        = $entity->getConfiguration();
            $new_dir_path    = $this->sherlockFinder->getSherlockDir();

            if (!$this->filesystem->exists($new_dir_path)) {
                $old = umask(0);
                $this->filesystem->mkdir($new_dir_path);
                umask($old);
            }

            switch ($sherlock["debug"]) {
                case false;
                    $this->pathfile = str_replace('%debug%', 'NO', $this->pathfile);
                    break;
                case true;
                    $this->pathfile = str_replace('%debug%', 'YES', $this->pathfile);
                    break;
            }

            $this->pathfile = str_replace('%clientFilePath%', $new_dir_path.'parmcom.client', $this->pathfile);
            $this->pathfile = str_replace('%clientCertifPath%', $new_dir_path.'certif', $this->pathfile);
            $this->pathfile = str_replace('%sherlockPath%', $new_dir_path.'parmcom.sherlock', $this->pathfile);

            $this->parmcomClient = str_replace('%autoResponseUrl%', $autoResponseUrl, $this->parmcomClient);
            $this->parmcomClient = str_replace('%cancelUrl%', $cancelUrl, $this->parmcomClient);
            $this->parmcomClient = str_replace('%returnUrl%', $returnUrl, $this->parmcomClient);

            $certificat          = $sherlock["certif"];
            $id                  = explode("!", $certificat)[1];
            $country             = explode("!", $certificat)[3];
            $extension           = explode("!", $this->pathfile)[11];
            $this->createFile('/certif.'.$country.'.'.$id.'.'.$extension, $certificat, $new_dir_path);
            $this->createFile('/parmcom.sherlock', $this->parmcomServer, $new_dir_path);
            $this->createFile('/parmcom.client.'.$id, $this->parmcomClient, $new_dir_path);
            $this->createFile('/pathfile', $this->pathfile, $new_dir_path);
        }
    }

    /**
     * @param LifecycleEventArgs $args
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     * @throws \Exception
     */
    public function postUpdate(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        if ($entity instanceof PaymentMethodTranslation && $entity->getTranslatable()->getMethod() == "sherlock") {
            $sherlock       = $entity->getConfiguration();
            $contentCertif  = $sherlock["certif"];
            $debug = $sherlock["debug"];
            if($debug == true)
            {
                $new_debug = "YES";
            }
            else {
                $new_debug = "NO";
            }

            $id = $this->get_string_between($contentCertif,"merchant_id!","!");
            $country = $this->get_string_between($contentCertif,"merchant_country!","!");
            $extension = $this->get_string_between($contentCertif,"certificate_type!","!");

            $certif_filename = $this->sherlockFinder->getSherlockDir().$this->sherlockFinder->getCompleteFileName('certif');
            $new_certif_filename = $this->sherlockFinder->getSherlockDir()."certif.".$country.".".$id.".".$extension;

            $parmcom_client_filename = $this->sherlockFinder->getSherlockDir().$this->sherlockFinder->getCompleteFileName('client');
            $new_parmcom_client_filename = $this->sherlockFinder->getSherlockDir()."parmcom.client.".$id;

            if ($certif_filename != $new_certif_filename) {
                $this->filesystem->rename($certif_filename, $new_certif_filename);
                $this->filesystem->rename($parmcom_client_filename, $new_parmcom_client_filename);
            }


            $pathfile_content = str_replace(explode("!",$this->sherlockFinder->getFileContent('pathfile'))[1],$new_debug,$this->sherlockFinder->getFileContent('pathfile'));

            $this->filesystem->dumpFile($this->sherlockFinder->getSherlockDir().$this->sherlockFinder->getCompleteFileName("certif"), $contentCertif);
            $this->filesystem->dumpFile($this->sherlockFinder->getSherlockDir().$this->sherlockFinder->getCompleteFileName('pathfile'), $pathfile_content);

        }
    }

    public function postRemove(LifecycleEventArgs $args)
    {
        $entity        = $args->getEntity();
        if ($entity instanceof PaymentMethod && $entity->getMethod() == "sherlock") {
            $this->filesystem->remove($this->sherlockFinder->getSherlockDir());
        }
    }

    /**
     * @param      $filename
     * @param      $content
     * @param      $dir_path
     * @param null $id
     */
    private function createFile($filename, $content, $dir_path, $id = null)
    {
        $new_file_path = $dir_path.$filename;
        if (!$this->filesystem->exists($new_file_path)) {
            $this->filesystem->touch($new_file_path);
            $this->filesystem->appendToFile($new_file_path, $content);
        } else {
            throw new \Exception("Ces fichiers existent déjà !");
        }
    }


    private function findFiles()
    {
        $data = $this->sherlockFinder->getFiles(
            [
                'pathfile',
                'parmcom.client',
                'parmcom.sherlock',
            ], 'sherlock_models_path'
        );

        $this->pathfile      = $this->sherlockFinder->getFileContent($data['pathfile']->getFilename(), 'sherlock_models_path');
        $this->parmcomClient = $this->sherlockFinder->getFileContent($data['parmcom.client']->getFilename(), 'sherlock_models_path');
        $this->parmcomServer = $this->sherlockFinder->getFileContent($data['parmcom.sherlock']->getFilename(), 'sherlock_models_path');
    }

    /**
     * @param $string
     * @param $start
     * @param $end
     * @return false|string|void
     */
    private function get_string_between($string, $start, $end)
    {
        $string = ' '.$string;
        $ini    = strpos($string, $start);
        if ($ini == 0) {
            return '';
        }
        $ini += strlen($start);
        $len = strpos($string, $end, $ini) - $ini;

        return substr($string, $ini, $len);
    }
}
