<?php

namespace Lc\CaracoleBundle\Twig;

use Lc\CaracoleBundle\Builder\Order\OrderShopBuilder;
use Lc\CaracoleBundle\Model\Merchant\MerchantInterface;
use Lc\CaracoleBundle\Model\Order\OrderShopInterface;
use Lc\CaracoleBundle\Model\Section\SectionInterface;
use Lc\CaracoleBundle\Model\User\UserMerchantInterface;
use Lc\CaracoleBundle\Repository\Config\TaxRateStore;
use Lc\CaracoleBundle\Repository\Config\UnitStore;
use Lc\CaracoleBundle\Repository\Merchant\MerchantStore;
use Lc\CaracoleBundle\Repository\Order\OrderShopStore;
use Lc\CaracoleBundle\Repository\Product\ProductCategoryStore;
use Lc\CaracoleBundle\Repository\Reminder\ReminderStore;
use Lc\CaracoleBundle\Repository\Section\SectionStore;
use Lc\CaracoleBundle\Resolver\MerchantResolver;
use Lc\CaracoleBundle\Resolver\SectionResolver;
use Lc\CaracoleBundle\Resolver\VisitorResolver;
use Lc\SovBundle\Solver\Setting\SettingSolver;
use Symfony\Component\Security\Core\Security;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class StoreTwigExtension extends AbstractExtension
{
    protected MerchantStore $merchantStore;
    protected SectionStore $sectionStore;
    protected ReminderStore $reminderStore;
    protected MerchantResolver $merchantResolver;
    protected SectionResolver $sectionResolver;
    protected UnitStore $unitStore;
    protected TaxRateStore $taxRateStore;
    protected ProductCategoryStore $productCategoryStore;
    protected OrderShopStore $orderShopStore;
    protected SettingSolver $settingSolver;
    protected OrderShopBuilder $orderShopBuilder;
    protected Security $security;
    protected VisitorResolver $visitorResolver;

    public function __construct(
            MerchantResolver $merchantResolver,
            SectionResolver $sectionResolver,
            MerchantStore $merchantStore,
            SectionStore $sectionStore,
            ReminderStore $reminderStore,
            UnitStore $unitStore,
            TaxRateStore $taxRateStore,
            ProductCategoryStore $productCategoryStore,
            OrderShopStore $orderShopStore,
            SettingSolver $settingSolver,
            OrderShopBuilder $orderShopBuilder,
            Security $security,
            VisitorResolver $visitorResolver
    ) {
        $this->merchantResolver = $merchantResolver;
        $this->sectionResolver = $sectionResolver;
        $this->merchantStore = $merchantStore;
        $this->sectionStore = $sectionStore;
        $this->reminderStore = $reminderStore;
        $this->unitStore = $unitStore;
        $this->taxRateStore = $taxRateStore;
        $this->productCategoryStore = $productCategoryStore;
        $this->orderShopStore = $orderShopStore;
        $this->settingSolver = $settingSolver;
        $this->orderShopBuilder = $orderShopBuilder;
        $this->security = $security;
        $this->visitorResolver = $visitorResolver;
    }

    public function getFunctions()
    {
        return array(
                new TwigFunction('carac_sections', [$this, 'getSections']),
                new TwigFunction('carac_section_current', [$this, 'getSectionCurrent']),
                new TwigFunction('carac_cart_current', [$this, 'getCartCurrent']),
                new TwigFunction('carac_merchants', [$this, 'getMerchants']),
                new TwigFunction('carac_reminders', [$this, 'getReminders']),
                new TwigFunction('carac_units', [$this, 'getUnits']),
                new TwigFunction('carac_tax_rates', [$this, 'getTaxRates']),
                new TwigFunction('carac_reduction_cart_codes', [$this, 'getTaxRates']),

                new TwigFunction('product_categories', [$this, 'getProductCategories']),
                new TwigFunction('cart_current', [$this, 'getCartCurrent']),
                new TwigFunction('cart_current_visited', [$this, 'getCartCurrentVisited']),
                new TwigFunction('merchant_current', [$this, 'getMerchantCurrent']),
                new TwigFunction('user_merchant_current', [$this, 'getUserMerchantCurrent']),
                new TwigFunction('section_current', [$this, 'getSectionCurrent']),
                new TwigFunction('section_default', [$this, 'getSectionDefault']),
                new TwigFunction('section_current_default', [$this, 'getSectionCurrentDefault']),
                new TwigFunction('section_current_visited', [$this, 'getSectionCurrentVisited']),
                new TwigFunction('is_out_of_sections', [$this, 'isOutOfSections']),
                new TwigFunction('is_inside_section', [$this, 'isInsideSection']),
                new TwigFunction('section_current_slug', [$this, 'getSectionCurrentSlug']),
                new TwigFunction('section_current_default_slug', [$this, 'getSectionCurrentDefaultSlug']),
                new TwigFunction('section_current_visited_slug', [$this, 'getSectionCurrentVisitedSlug']),
                new TwigFunction('merchant_setting', [$this, 'getMerchantSetting']),
                new TwigFunction('merchant_setting_current', [$this, 'getMerchantSettingCurrent']),
                new TwigFunction('section_setting', [$this, 'getSectionSetting']),
                new TwigFunction('section_setting_current', [$this, 'getSectionSettingCurrent']),
                new TwigFunction('visitor_current', [$this, 'getVisitorCurrent']),

        );
    }

    public function isInsideSection(): bool
    {
        return (bool) $this->sectionResolver->getCurrent();
    }

    public function isOutOfSections()
    {
        return $this->sectionResolver->isOutOfSection();
    }

    private $sections = null;
    public function getSections()
    {
        if(!$this->sections){
            $this->sections = $this->sectionStore
                ->setMerchant($this->merchantResolver->getCurrent())
                ->getOnline();
        }
        return $this->sections;
    }

    public function getMerchants()
    {
        return $this->merchantStore->getOnline();
    }

    public function getSectionCurrent(): ?SectionInterface
    {
        return $this->sectionResolver->getCurrent();
    }

    public function getSectionDefault(): ?SectionInterface
    {
        return $this->sectionStore->setMerchant($this->merchantResolver->getCurrent())->getOneDefault();
    }

    public function getSectionCurrentDefault(): ?SectionInterface
    {
        return $this->sectionResolver->getCurrent(true);
    }

    public function getSectionCurrentVisited(): ?SectionInterface
    {
        return $this->sectionResolver->getCurrent(true, true);
    }

    public function getSectionCurrentSlug(): string
    {
        return $this->sectionResolver->getCurrent()->getSlug();
    }

    public function getSectionCurrentDefaultSlug(): string
    {
        return $this->sectionResolver->getCurrent(true)->getSlug();
    }

    public function getSectionCurrentVisitedSlug(): string
    {
        return $this->sectionResolver->getCurrent(true, true)->getSlug();
    }

    public function getCartCurrent(): OrderShopInterface
    {
        return $this->orderShopBuilder->createIfNotExist(
                $this->sectionResolver->getCurrent(),
                $this->security->getUser(),
                $this->visitorResolver->getCurrent(),
                true
        );
    }

    public function getCartCurrentVisited(): OrderShopInterface
    {
        return $this->orderShopBuilder->createIfNotExist(
                $this->sectionResolver->getCurrent(true, true),
                $this->security->getUser(),
                $this->visitorResolver->getCurrent(),
                true
        );
    }

    public function getMerchantCurrent(): MerchantInterface
    {
        return $this->merchantResolver->getCurrent();
    }

    public function getUserMerchantCurrent(): ?UserMerchantInterface
    {
        return $this->merchantResolver->getUserMerchant();
    }

    public function getMerchantSetting(MerchantInterface $merchant, string $settingName): string
    {
        return $this->settingSolver->getSettingValue($merchant, $settingName);
    }

    public function getMerchantSettingCurrent(string $settingName): ?string
    {
        return $this->settingSolver->getSettingValue($this->getMerchantCurrent(), $settingName);
    }

    public function getSectionSetting(SectionInterface $section, string $settingName): ?string
    {
        return $this->settingSolver->getSettingValue($section, $settingName);
    }

    public function getSectionSettingCurrent(string $settingName)
    {
        return $this->settingSolver->getSettingValue($this->getSectionCurrent(), $settingName);
    }

    public function getProductCategories()
    {
        return $this->productCategoryStore
                ->setSection($this->sectionResolver->getCurrent())
                ->getParent();
    }

    public function getReminders($params = [])
    {
        return $this->reminderStore
                ->setMerchant($this->merchantResolver->getCurrent())
                ->setSection($this->sectionResolver->getCurrent())
                ->get($params);
    }

    public function getUnits()
    {
        return $this->unitStore->getAsArray();
    }

    public function getTaxRates()
    {
        return $this->taxRateStore->setMerchant($this->merchantResolver->getCurrent())->getAsArray();
    }

    public function getReductionCartCodes()
    {
        //TODO mettre à jour une fois les repo fait
        return array();
    }

    public function getVisitorCurrent()
    {
        return $this->visitorResolver->getCurrent();
    }
}