<?php

namespace KupShop\KupShopBundle\Util\Compat;

use KupShop\KupShopBundle\Context\CountryContext;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Context\DomainContext;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Context\PriceLevelContext;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\StringUtil;
use KupShop\KupShopBundle\Wrapper\PriceLevelWrapper;

/**
 * @deprecated tohle je jen pro starý šablony, nikdy mě nepoužívej!! Vše co mám je v contextech a jinde
 */
class CtrlLoader implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
{
    private $container = [];

    public function setContainer(array $container)
    {
        $this->container = $container;
    }

    /**
     * @return bool|\User
     */
    public function getUser()
    {
        return Contexts::get(UserContext::class)->getActive();
    }

    /**
     * @param bool|\User $user
     */
    public function setUser($user)
    {
        Contexts::get(UserContext::class)->activate($user);
    }

    public function field_user()
    {
        return $this->getUser();
    }

    public function field_logged(): bool
    {
        return (bool) $this->getUser();
    }

    public function field_currUrl()
    {
        // RequestStack nakonec jsme dali pryč, protože když se renderovaly fragmenty kvůli full-page cache, nebyl tam top request a špatně
        // se vracely '$ctrl.currUrl' - vracelo url fragmentu místo url originálního requestu
        $request = SymfonyBridge::getCurrentRequest();

        return [
            'Abs' => $request->getUri(),
            'Rel' => $request->getRequestUri(),
            'Entity' => urlencode($request->getUri()),
        ];
    }

    /**
     * @return false|int
     */
    public function field_id()
    {
        $user = $this->getUser();

        return $user->id ?? false;
    }

    public function field_customData()
    {
        if (!$this->getUser()) {
            return [];
        }

        return $this->getUser()->getCustomData() ?? [];
    }

    public function field_active_language()
    {
        return $this->getContextActiveId(LanguageContext::class);
    }

    public function field_active_language_code()
    {
        return Contexts::get(LanguageContext::class)->getActive()->getLocale();
    }

    public function field_active_currency()
    {
        return $this->getContextActiveId(CurrencyContext::class);
    }

    public function field_active_country()
    {
        return $this->getContextActiveId(CountryContext::class);
    }

    public function field_active_domain()
    {
        return $this->getContextActiveId(DomainContext::class);
    }

    private function getContextActiveId($context)
    {
        return Contexts::get($context)->getActiveId();
    }

    public function offsetSet($offset, $value): void
    {
        throw new \Exception('OffsetSet in CtrlLoader is forbidden!');
    }

    public function offsetExists($offset): bool
    {
        return isset($this->container[$offset]) || method_exists($this, $this->offsetMethod($offset));
    }

    public function offsetUnset($offset): void
    {
        throw new \Exception('OffsetUnset in CtrlLoader is forbidden!');
    }

    public function &offsetGet($offset): mixed
    {
        $method = $this->offsetMethod($offset);
        if (method_exists($this, $method)) {
            $res = call_user_func([$this, $method]);

            return $res;
        }

        if (isset($this->container[$offset])) {
            return $this->container[$offset];
        }

        $user = $this->getUser();
        if (isset($user->$offset)) {
            return $user->$offset;
        } elseif (!empty($user) && $offset === 'id_price_level') {
            $priceLevel = $user->getPriceLevel();

            if ($priceLevel) {
                return $priceLevel->id;
            }

            $null = null;

            return $null;
        } else {
            $null = null;

            return $null;
        }
    }

    public function offsetMethod($offset)
    {
        return 'field_'.$offset;
    }

    public function getIterator(): \Traversable
    {
        return new \ArrayIterator($this->container);
    }

    public function count(): int
    {
        return count($this->container);
    }

    public function field_dealerPricelevel()
    {
        $priceLevel = ServiceContainer::getService(PriceLevelContext::class)->getActive();

        if (!$priceLevel) {
            return null;
        }

        return PriceLevelWrapper::wrap($priceLevel);
    }

    public function field_currency()
    {
        return ServiceContainer::getService(CurrencyContext::class)->getActiveId();
    }

    public function field_dealer()
    {
        if ($this->getUser()) {
            if (Contexts::get(UserContext::class)->isDealer()) {
                return 'Y';
            }
        }

        return 'N';
    }

    public function field_login()
    {
        return $this->getUser() ? $this->getUser()->email : '';
    }

    public function hasGroupId($groupId)
    {
        return $this->getUser() ? $this->getUser()->hasGroupId($groupId) : false;
    }

    public function isType(string $type): bool
    {
        return $this->getUser() && $this->getUser()->isType($type);
    }

    public function getType(string $type): ?array
    {
        return $this->getUser() ? $this->getUser()->getType($type) : null;
    }

    public function __debugInfo()
    {
        return $this->container;
    }

    /**
     * Specify data which should be serialized to JSON.
     */
    public function jsonSerialize(): mixed
    {
        $methods = get_class_methods($this);
        $methodFields = [];

        foreach ($methods as $method) {
            if (!StringUtil::startsWith($method, 'field_')) {
                continue;
            }

            [$_, $fieldName] = explode('field_', $method);

            $methodFields[$fieldName] = $this->{$method}();
        }

        return array_merge($this->container, $methodFields);
    }
}
