<?php 
 
namespace Customize\EventListener; 
 
use Customize\Event\LmEvents; 
use Customize\Service\AutoLoadService; 
use Customize\Service\Karte\KarteService; 
use Eccube\Entity\Customer; 
use Eccube\Entity\Order; 
use Eccube\Event\EccubeEvents; 
use Eccube\Event\EventArgs; 
use Eccube\Event\TemplateEvent; 
use Customize\Service\CartService; 
use Lm\Engine\EC\Entity\GoodsWithRelated; 
use Lm\Entity\OrderHeader; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\RequestStack; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpFoundation\Session\SessionInterface; 
use Symfony\Component\HttpKernel\Event\ResponseEvent; 
use Symfony\Component\HttpKernel\KernelEvents; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; 
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; 
use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface; 
use Twig\Environment; 
use Symfony\Component\HttpFoundation\StreamedResponse; 
 
class KarteEventListener implements EventSubscriberInterface, LogoutHandlerInterface 
{ 
 
    const SESSION_FRONT_SIGNUP = 'karte.front.signup'; 
 
    const SESSION_FRONT_LOGIN = 'karte.front.login'; 
 
    const SESSION_FRONT_LOGOUT = 'karte.front.logout'; 
 
    const SESSION_FRONT_FAVORITE_ADD = 'karte.front.favorite.add'; 
 
    const SESSION_FRONT_FAVORITE_DELETE = 'karte.front.favorite.delete'; 
 
    /** 
     * @var RequestStack 
     */ 
    private $requestStack; 
 
    /** 
     * @var SessionInterface 
     */ 
    private $session; 
 
    /** 
     * @var TokenStorageInterface 
     */ 
    private $tokenStorage; 
    private $karteService; 
    private $cartService; 
 
    /** 
     * @var Environment 
     */ 
    private $twig; 
 
    /** 
     * @var AutoLoadService 
     */ 
    private $autoLoadService; 
 
    public function __construct(RequestStack          $requestStack, 
                                SessionInterface      $session, 
                                KarteService          $karteService, 
                                CartService           $cartService, 
                                TokenStorageInterface $tokenStorage, 
                                Environment           $twig, 
                                AutoLoadService       $autoLoadService) 
    { 
        // 
        $this->requestStack = $requestStack; 
        $this->session = $session; 
        $this->tokenStorage = $tokenStorage; 
        $this->karteService = $karteService; 
        $this->cartService = $cartService; 
        $this->twig = $twig; 
        $this->autoLoadService = $autoLoadService; 
    } 
 
    public function onKernelResponse(ResponseEvent $event) 
    { 
        // 
        $response = $event->getResponse(); 
        $request = $event->getRequest(); 
        // 
        if (!$event->isMasterRequest()) { 
            // 
            return; 
        } 
        // 
        if ($request->isXmlHttpRequest()) { 
            return; 
        } 
        // 
        if ($this->autoLoadService->GetNarikawariSession(false)) { 
            return; 
        } 
        // 
        $this->injectIndex($response); 
    } 
 
    protected function injectIndex(Response $response) 
    { 
        if ($response instanceof StreamedResponse) { 
            return; 
        } 
 
        $content = $response->getContent(); 
 
        $content = preg_replace_callback("/<head[^>]*?>/", function ($matches) { 
            return "{$matches[0]}\n\n{$this->twig->render('Karte/index.twig')}"; 
        }, $content); 
 
        $response->setContent($content); 
    } 
 
    /** 
     * @inheritDoc 
     */ 
    public static function getSubscribedEvents() 
    { 
        return [ 
            // 
            KernelEvents::RESPONSE => 'onKernelResponse', 
            // 
            'Entry/activate.twig' => 'onEntryActivate', 
            'Shopping/index.twig' => 'onEntryActivate', 
            'Mypage/index.twig' => 'onEntryActivate', 
            'Top/index.twig' => 'onEntryActivate', 
            'security.interactive_login' => 'onInteractiveLogin', 
            //'Page/sub-category.twig' => 'onProductList', 
            'Item/detail.twig' => 'onProductDetail', 
            'Mypage/favorite.twig' => 'onFavoriteUpdate', 
            'Cart/index.twig' => 'onTrackInformationOfCart', // for event Cart 
            'Shopping/complete.twig' => 'onPurchaseCompleted', // for event Purchase 
            'Estimate/index.twig' => 'onQuotation', // for event Quotation simulation 
            'Mypage/update.twig' => 'onMyPageUpdateInformation', // for event User attribute information 
            'Mypage/withdraw_complete.twig' => 'onMyPageUpdateInformation', // for event User attribute information 
            'Mitsumori/index.twig' => 'onQuotation', // for event create Quotation 
            'Contact/complete.twig' => 'onEntryActivate', // for event email inquiry 
            EccubeEvents::FRONT_ENTRY_INDEX_COMPLETE => 'onEccubeFrontEntryIndexComplete', 
            LmEvents::FRONT_PRODUCT_FAVORITE_ADD_COMPLETE => 'onLmFrontFavoriteAddComplete', 
            LmEvents::FRONT_PRODUCT_FAVORITE_DELETE_COMPLETE => 'onLmFrontFavoriteDeleteComplete', 
            LmEvents::SESSION_FRONT_PRODUCT_USER_CART_STEP2_REGISTER_COMPLETED => 'onCartStep2RegisterCompleted', 
            LmEvents::SESSION_FRONT_PRODUCT_CART_ADD_PRODUCT => 'onAddProduct', 
            LmEvents::SESSION_FRONT_PRODUCT_CART_DELETE_PRODUCT => 'onDeleteProduct', 
            LmEvents::SESSION_FRONT_SEND_QUOTATION_BY_EMAIL => 'onSendQuotationByEmail', 
            LmEvents::SESSION_FRONT_SEND_QUOTATION_BY_FAX => 'onSendQuotationByFax', 
        ]; 
    } 
 
    public function onEntryActivate(TemplateEvent $event) 
    { 
        $parameter = $event->hasParameter('Karte') ? $event->getParameter('Karte') : []; 
        /** 
         * @var Customer $customer 
         */ 
        if ($token = $this->tokenStorage->getToken()) { 
            if (($customer = $token->getUser()) 
                && ($customer instanceof Customer) 
                && ($lmCustomer = $customer->getLmCustomer())) { 
                $parameter += [ 
                    'customer' => $lmCustomer, 
                ]; 
            } 
        } 
        if ($this->session->remove(self::SESSION_FRONT_SIGNUP)) { 
            $event->addSnippet('Karte/signup.twig'); 
            if ($lmCustomer) { 
                $event->addSnippet('Karte/identify.twig'); 
            } 
        } 
        if ($this->session->remove(self::SESSION_FRONT_LOGIN)) { 
            $parameter += [ 
                'login' => [ 
                    'status' => true, 
                ], 
            ]; 
            $event->addSnippet('Karte/login.twig'); 
            if ($lmCustomer) { 
                $event->addSnippet('Karte/identify.twig'); 
            } 
        } 
        if ($this->session->remove(self::SESSION_FRONT_LOGOUT)) { 
            $parameter += [ 
                'login' => [ 
                    'status' => false, 
                ], 
            ]; 
            $event->addSnippet('Karte/login.twig'); 
        } 
        if ($this->session->remove(LmEvents::SESSION_FRONT_PRODUCT_USER_CART_STEP2_REGISTER_COMPLETED)) { 
            $cart = $this->cartService->getCart(); 
            if (!empty($cart)) { 
                $customer = $cart->getCustomer(); 
                $parameter += $this->karteService->getAttributeForPersonalInfomation($customer); 
                $event->addSnippet('Karte/attribute.twig'); 
            } 
        } 
        if ($email = $this->session->remove(LmEvents::SESSION_FRONT_MYPAGE_EMAIL_INQUIRY)) { 
            $parameter += [ 
                'email_inquiry' => [ 
                    'email' => $email 
                ] 
            ]; 
            $event->addSnippet('Karte/email_inquiry.twig'); 
        } 
        if (!empty($parameter)) { 
            $event->setParameter('Karte', $parameter); 
        } 
    } 
 
    public function onEccubeFrontEntryIndexComplete(EventArgs $event) 
    { 
        $this->session->set(self::SESSION_FRONT_SIGNUP, true); 
    } 
 
    public function onInteractiveLogin(InteractiveLoginEvent $event) 
    { 
        $this->session->set(self::SESSION_FRONT_LOGIN, true); 
        $this->session->set(LmEvents::SESSION_FRONT_PRODUCT_CART_STEP2_LOGIN_COMPLETED, true); 
    } 
 
    /** 
     * @inheritDoc 
     */ 
    public function logout(Request $request, Response $response, ?TokenInterface $token) 
    { 
        // 
        $this->session->set(self::SESSION_FRONT_LOGOUT, true); 
    } 
 
    public function onProductList(TemplateEvent $event) 
    { 
        // 
        $karte = $event->hasParameter('Karte') ? $event->getParameter('Karte') : []; 
        // 
        if ($request = $this->requestStack->getCurrentRequest()) { 
            // 
            $karte['list_url'] = $request->getPathInfo(); 
        } 
        // 
        if (!empty($karte)) { 
            // 
            $event->setParameter('Karte', $karte); 
        } 
        // 
        $event->addSnippet('Karte/view_list.twig'); 
    } 
 
    public function onProductDetail(TemplateEvent $event) 
    { 
        // 
        $karte = $event->hasParameter('Karte') ? $event->getParameter('Karte') : []; 
        // 
        if ($request = $this->requestStack->getCurrentRequest()) { 
            // 
            $karte['item_url'] = $request->getPathInfo(); 
        } 
        // 
        if (!empty($karte)) { 
            // 
            $event->setParameter('Karte', $karte); 
        } 
        // 
        $event->addSnippet('Karte/view_item.twig'); 
    } 
 
    public function onFavoriteUpdate(TemplateEvent $event) 
    { 
        // 
        $karte = $event->hasParameter('Karte') ? $event->getParameter('Karte') : []; 
        // 
        if (!isset($karte['favorite'])) { 
            // 
            $karte['favorite'] = []; 
        } 
        // 
        if ($goodsList = $event->getParameter('data')) { 
            // 
            $karte['favorite']['items'] = array_map(function ($goods) { 
                // 
                if ($_goods = new GoodsWithRelated($goods['goods_id'])) { 
                    // 
                    return [ 
                        'item_id' => $_goods->getGoodsId(), 
                        'name' => $_goods->getGoodsName(), 
                        'item_url' => "/item/{$_goods->getItemId()}.html", // TODO: 
                        "l_category_name" => $_goods->getMainCategory()->getMainCategoryName(), 
                        "s_category_name" => $_goods->getMainCategory()->getCategoryName(), 
                        "l_category_cd" => $_goods->getMainCategory()->getMainCategoryWebname(), 
                        "s_category_cd" => $_goods->getMainCategory()->getCategoryWebname(), 
                    ]; 
                } 
            }, $goodsList); 
            // 
            $karte['favorite']['status'] = !empty($karte['favorite']['items']); 
            $karte['favorite']['quantity'] = count($karte['favorite']['items']); 
        } 
        // 
        if ($added = $this->session->remove(self::SESSION_FRONT_FAVORITE_ADD)) { 
            // 
            $karte['favorite']['added_item_id'] = $added['goods_id']; 
        } 
        // 
        if ($deleted = $this->session->remove(self::SESSION_FRONT_FAVORITE_DELETE)) { 
            // 
            $karte['favorite']['deleted_item_id'] = $deleted['goods_id']; 
        } 
        // 
        if (!empty($karte)) { 
            // 
            $event->setParameter('Karte', $karte); 
        } 
        // 
        $event->addSnippet('Karte/favorite.twig'); 
    } 
 
    public function onLmFrontFavoriteAddComplete(EventArgs $event) 
    { 
        $this->session->set(self::SESSION_FRONT_FAVORITE_ADD, $event->getArguments()); 
    } 
 
    public function onLmFrontFavoriteDeleteComplete(EventArgs $event) 
    { 
        $this->session->set(self::SESSION_FRONT_FAVORITE_DELETE, $event->getArguments()); 
    } 
 
    public function onAddProduct(EventArgs $event) 
    { 
        $this->session->set(LmEvents::SESSION_FRONT_PRODUCT_CART_ADD_PRODUCT, $event->getArguments()); 
    } 
 
    public function onDeleteProduct(EventArgs $event) 
    { 
        $this->session->set(LmEvents::SESSION_FRONT_PRODUCT_CART_DELETE_PRODUCT, $event->getArguments()); 
    } 
    public function onSendQuotationByEmail(EventArgs $event) 
    { 
        $this->session->set(LmEvents::SESSION_FRONT_SEND_QUOTATION_BY_EMAIL, $event->getArguments()); 
    } 
    public function onSendQuotationByFax(EventArgs $event) 
    { 
        $this->session->set(LmEvents::SESSION_FRONT_SEND_QUOTATION_BY_FAX, $event->getArguments()); 
    } 
 
    public function onTrackInformationOfCart(TemplateEvent $event) 
    { 
        $karte = $event->hasParameter('Karte') ? $event->getParameter('Karte') : []; 
        $cart = $this->cartService->getCart(); 
        if ($this->session->remove(LmEvents::SESSION_FRONT_QUOTATION_SIMULATION)) { 
            if (!empty($cart)) { 
                $karte['quotation_simulation'] = $this->karteService->getAttributesForCart($cart); 
                $event->addSnippet('Karte/quotation_simulation.twig'); 
            } 
        } 
        if ($this->session->remove(LmEvents::SESSION_FRONT_PRODUCT_CART)) { 
            if (!empty($cart)) { 
                $data = $this->karteService->getAttributesForCart($cart); 
                if (!empty($data)) { 
                    $karte['cart'] = $data; 
                    $event->addSnippet('Karte/cart.twig'); 
                } 
            } 
        } 
        if (!empty($karte)) { 
            $event->setParameter('Karte', $karte); 
        } 
    } 
 
    public function onQuotation(TemplateEvent $event) { 
        $karte = $event->hasParameter('Karte') ? $event->getParameter('Karte') : []; 
        if ($this->session->remove(LmEvents::SESSION_FRONT_QUOTATION_CREATE)) { 
            $cart = $this->cartService->getCart(); 
            if (!empty($cart)) { 
                $karte['quotation_create'] = $this->karteService->getAttributesForCart($cart); 
                $event->addSnippet('Karte/quotation_create.twig'); 
            } 
        } 
        if ($dataQuotationSendByEmail = $this->session->remove(LmEvents::SESSION_FRONT_SEND_QUOTATION_BY_EMAIL)) { 
            if (!empty($dataQuotationSendByEmail)) { 
                $karte['quotation_by_email'] = $dataQuotationSendByEmail; 
                $event->addSnippet('Karte/quotation_by_email.twig'); 
            } 
        } 
        if ($dataQuotationSendByFax = $this->session->remove(LmEvents::SESSION_FRONT_SEND_QUOTATION_BY_FAX)) { 
            if (!empty($dataQuotationSendByFax)) { 
                $karte['quotation_by_fax'] = $dataQuotationSendByFax; 
                $event->addSnippet('Karte/quotation_by_fax.twig'); 
            } 
        } 
        if (!empty($karte)) { 
            $event->setParameter('Karte', $karte); 
        } 
    } 
 
    public function onPurchaseCompleted(TemplateEvent $event) 
    { 
        /** 
         * @var Order $order 
         * @var OrderHeader $orderHeader 
         */ 
        $karte = $event->hasParameter('Karte') ? $event->getParameter('Karte') : []; 
        if (!isset($karte['cart'])) { 
            $karte['cart'] = []; 
        } 
        // get variable from view purchase completed 
        $dataLayer = $event->getParameter('dataLayer'); 
        // 
        if (!($orderHeader = $event->getParameter('orderHeader'))) { 
            return; 
        } else if ($orderHeader->getOhType() === OrderHeader::TYPE_SAMPLE || $orderHeader->getOhType() === OrderHeader::TYPE_CATALOG) { 
            return; 
        } 
        // 
        if (!($Order = $event->getParameter('Order'))) { 
            return; 
        } 
        // 
        if (empty($dataLayer[1])) { 
            return; 
        } 
        $order = $event->getParameter('Order'); 
        $customer = $order->getCustomer(); 
        $karte['buy'] = $this->karteService->getAttributesForPurchase($event, $dataLayer); 
        $karte['buy_stats'] = $this->karteService->getAttributesForUserPurchaseInfomation($customer); 
        $event->addSnippet('Karte/buy_stats.twig'); 
        $event->addSnippet('Karte/buy.twig'); 
        if (!empty($karte)) { 
            $event->setParameter('Karte', $karte); 
        } 
    } 
 
    public function onCartStep2RegisterCompleted(EventArgs $event) 
    { 
        $this->session->set(LmEvents::SESSION_FRONT_PRODUCT_USER_CART_STEP2_REGISTER_COMPLETED, $event->getArguments()); 
    } 
 
    public function onMyPageUpdateInformation(TemplateEvent $event) 
    { 
        $parameter = $event->hasParameter('Karte') ? $event->getParameter('Karte') : []; 
        if (in_array(true, [$this->session->remove(LmEvents::SESSION_FRONT_PRODUCT_CART_STEP2_LOGIN_COMPLETED), $this->session->remove(LmEvents::SESSION_FRONT_MYPAGE_USER_UPDATE_INFOMATION)])) { 
            /** 
             * @var Customer $customer 
             */ 
            $customer = $this->tokenStorage->getToken()->getUser(); 
            $parameter = $this->karteService->getAttributeForPersonalInfomation($customer, null); 
        } 
        if ($dataUserUnsubscribe = $this->session->remove(LmEvents::SESSION_FRONT_MYPAGE_USER_UNSUBSCRIBE)) { 
            $customer = $dataUserUnsubscribe['customer']; 
            $unsubscribeDate = $dataUserUnsubscribe['unsubscribeDate']; 
            $parameter = $this->karteService->getAttributeForPersonalInfomation($customer, $unsubscribeDate); 
        } 
        if (!empty($parameter)) { 
            $event->addSnippet('Karte/attribute.twig'); 
            $event->setParameter('Karte', $parameter); 
        } 
    } 
}