<?php

namespace KupShop\GTMBundle\Utils;

use KupShop\GTMBundle\Exception\GTMException;
use KupShop\GTMBundle\PageType\CommonPageType;
use KupShop\GTMBundle\PageType\OtherPageType;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Views\View;
use Symfony\Component\DependencyInjection\ContainerInterface;

class GTMLoader
{
    /**
     * @var ContainerInterface
     */
    private $container;

    private $pageTypes = [];
    private $ecommerceTypes = [];

    /**
     * @var CommonPageType
     */
    private $commonPageType;

    /**
     * GoogleTagManager constructor.
     */
    public function __construct(ContainerInterface $container, CommonPageType $commonPageType)
    {
        $this->container = $container;
        $this->commonPageType = $commonPageType;
    }

    /**
     * @return array|bool
     *
     * @throws \Exception
     */
    public function getData(View $view)
    {
        try {
            /* Nemuze byt v DI, protoze pak nefunguje v testech vnuceni vlastni instance classy DataContainer */
            $dataContainer = ServiceContainer::getService(DataContainer::class);
            $this->commonPageType->setView($view);
            $this->commonPageType->collectData($dataContainer);

            $specificPageType = ServiceContainer::getService($this->getPageType($view));
            $specificPageType->setView($view);
            $specificPageType->collectData($dataContainer);

            return $dataContainer->getDataLayer();
        } catch (\Error|\Exception $e) {
            $this->catchError($e, $view);

            return false;
        }
    }

    /**
     * @param null $view
     *
     * @throws \Exception
     */
    protected function catchError($e, $view = null)
    {
        if (isDevelopment()) {
            throw new \Exception($e);
        }
        $sentry = getRaven();
        $exception = new GTMException('GTM data error', previous: $e);
        $sentry->captureException($exception, ['extra' => [
            'page' => $view,
            'error_message' => $e->getMessage(),
        ]]);
    }

    public function setPageType($view, $pagetype)
    {
        $this->pageTypes[$view] = $pagetype;
    }

    /**
     * @internal param View $view
     */
    protected function getPageType(View $currentView)
    {
        foreach ($this->pageTypes as $view => $pageType) {
            if ($currentView instanceof $view) {
                return $pageType;
            }
        }

        return OtherPageType::class;
    }

    /**
     * ENHANCED ECOMMERCE LOADING.
     *
     * @return array|bool
     *
     * @throws \Exception
     */
    public function getEcommerceData($type, $data, ?View $view)
    {
        try {
            /* Nemuze byt v DI, protoze pak nefunguje v testech vnuceni vlastni instance classy DataContainer */
            $dataContainer = ServiceContainer::getService(DataContainer::class);

            $specificPageType = $this->getEcommerceType($type);
            $specificPageType->setView($view);

            if (!$specificPageType) {
                return [];
            }

            $specificPageType->setPageData($data);
            $specificPageType->getData($dataContainer);

            return $dataContainer->getDataLayer();
        } catch (\Error|\Exception $e) {
            $this->catchError($e, [$type, $data]);

            return false;
        }
    }

    public function addEcommerceType($type, $service)
    {
        $this->ecommerceTypes[$type] = $service;
    }

    /**
     * @return AbstractEcommerce|null
     *
     * @internal param View Abs
     * @internal param View $view
     */
    protected function getEcommerceType($type)
    {
        foreach ($this->ecommerceTypes as $serviceType => $service) {
            if ($type == $serviceType) {
                return ServiceContainer::getService($service);
            }
        }

        return null;
    }

    public function getPageTypes(): array
    {
        return $this->pageTypes;
    }

    public function getEcommerceTypes(): array
    {
        return $this->ecommerceTypes;
    }
}
