<?php

namespace Lc\CaracoleBundle\Controller;

use Lc\CaracoleBundle\Container\Address\AddressContainer;
use Lc\CaracoleBundle\Container\Config\TaxRateContainer;
use Lc\CaracoleBundle\Container\Config\UnitContainer;
use Lc\CaracoleBundle\Container\Credit\CreditHistoryContainer;
use Lc\CaracoleBundle\Container\Distribution\DistributionContainer;
use Lc\CaracoleBundle\Container\File\DocumentContainer;
use Lc\CaracoleBundle\Container\Merchant\MerchantContainer;
use Lc\CaracoleBundle\Container\Order\OrderPaymentContainer;
use Lc\CaracoleBundle\Container\Order\OrderProductContainer;
use Lc\CaracoleBundle\Container\Order\OrderProductReductionCatalogContainer;
use Lc\CaracoleBundle\Container\Order\OrderProductRefundContainer;
use Lc\CaracoleBundle\Container\Order\OrderReductionCartContainer;
use Lc\CaracoleBundle\Container\Order\OrderReductionCreditContainer;
use Lc\CaracoleBundle\Container\Order\OrderRefundContainer;
use Lc\CaracoleBundle\Container\Order\OrderShopContainer;
use Lc\CaracoleBundle\Container\Order\OrderStatusContainer;
use Lc\CaracoleBundle\Container\Order\OrderStatusHistoryContainer;
use Lc\CaracoleBundle\Container\PointSale\PointSaleContainer;
use Lc\CaracoleBundle\Container\Product\ProductCategoryContainer;
use Lc\CaracoleBundle\Container\Product\ProductContainer;
use Lc\CaracoleBundle\Container\Product\ProductFamilyContainer;
use Lc\CaracoleBundle\Container\Product\ProductFamilySectionPropertyContainer;
use Lc\CaracoleBundle\Container\Product\QualityLabelContainer;
use Lc\CaracoleBundle\Container\Reduction\ReductionCartContainer;
use Lc\CaracoleBundle\Container\Reduction\ReductionCatalogContainer;
use Lc\CaracoleBundle\Container\Reduction\ReductionCreditContainer;
use Lc\CaracoleBundle\Container\Section\OpeningContainer;
use Lc\CaracoleBundle\Container\Section\SectionContainer;
use Lc\CaracoleBundle\Container\Setting\MerchantSettingContainer;
use Lc\CaracoleBundle\Container\Setting\SectionSettingContainer;
use Lc\CaracoleBundle\Container\User\UserMerchantContainer;
use Lc\CaracoleBundle\Container\User\UserPointSaleContainer;
use Lc\CaracoleBundle\Container\User\VisitorContainer;
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\Model\User\VisitorInterface;
use Lc\CaracoleBundle\Notification\MailMailjetNotification;
use Lc\CaracoleBundle\Resolver\MerchantResolver;
use Lc\CaracoleBundle\Resolver\SectionResolver;
use Lc\CaracoleBundle\Solver\Price\PriceSolver;
use Lc\SovBundle\Model\User\UserInterface;
use Lc\SovBundle\Solver\Setting\SettingSolver;
use Symfony\Component\Security\Core\Security;

trait ControllerTrait
{
    public static function getSubscribedServices()
    {
        return array_merge(
                parent::getSubscribedServices(),
                [
                        MailMailjetNotification::class => MailMailjetNotification::class,
                        PriceSolver::class => PriceSolver::class,
                        MerchantResolver::class => MerchantResolver::class,
                        SectionResolver::class => SectionResolver::class,
                        OrderShopContainer::class => OrderShopContainer::class,
                        AddressContainer::class => AddressContainer::class,
                        TaxRateContainer::class => TaxRateContainer::class,
                        UnitContainer::class => UnitContainer::class,
                        CreditHistoryContainer::class => CreditHistoryContainer::class,
                        DocumentContainer::class => DocumentContainer::class,
                        MerchantContainer::class => MerchantContainer::class,
                        OrderPaymentContainer::class => OrderPaymentContainer::class,
                        OrderProductContainer::class => OrderProductContainer::class,
                        OrderProductReductionCatalogContainer::class => OrderProductReductionCatalogContainer::class,
                        OrderProductRefundContainer::class => OrderProductRefundContainer::class,
                        OrderReductionCartContainer::class => OrderReductionCartContainer::class,
                        OrderReductionCreditContainer::class => OrderReductionCreditContainer::class,
                        OrderRefundContainer::class => OrderRefundContainer::class,
                        OrderStatusContainer::class => OrderStatusContainer::class,
                        OrderStatusHistoryContainer::class => OrderStatusHistoryContainer::class,
                        PointSaleContainer::class => PointSaleContainer::class,
                        ProductCategoryContainer::class => ProductCategoryContainer::class,
                        ProductContainer::class => ProductContainer::class,
                        ProductFamilyContainer::class => ProductFamilyContainer::class,
                        ReductionCartContainer::class => ReductionCartContainer::class,
                        ReductionCatalogContainer::class => ReductionCatalogContainer::class,
                        ReductionCreditContainer::class => ReductionCreditContainer::class,
                        OpeningContainer::class => OpeningContainer::class,
                        SectionContainer::class => SectionContainer::class,
                        MerchantSettingContainer::class => MerchantSettingContainer::class,
                        SectionSettingContainer::class => SectionSettingContainer::class,
                        UserMerchantContainer::class => UserMerchantContainer::class,
                        UserPointSaleContainer::class => UserPointSaleContainer::class,
                        VisitorContainer::class => VisitorContainer::class,
                        DistributionContainer::class => DistributionContainer::class,
                        ProductFamilySectionPropertyContainer::class => ProductFamilySectionPropertyContainer::class,
                        QualityLabelContainer::class => QualityLabelContainer::class,
                ]
        );
    }

    public function getMailMailjetNotification()
    {
        return $this->get(MailMailjetNotification::class);
    }

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

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

    public function getSettingSolver(): SettingSolver
    {
        return $this->get(SettingSolver::class);
    }

    public function getSettingValue($entity, $settingName)
    {
        return $this->getSettingSolver()->getSettingValue($entity, $settingName);
    }

    public function getUserCurrent(): ?UserInterface
    {
        return $this->get(Security::class)->getUser();
    }

    public function getVisitorCurrent(): VisitorInterface
    {
        return $this->getVisitorContainer()->getResolver()->getCurrent();
    }

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

    public function getUserMerchantCurrent(): UserMerchantInterface
    {
        return $this->getUserMerchantContainer()->getBuilder()->createIfNotExist(
                $this->getUserCurrent(),
                $this->getMerchantCurrent()
        );
    }

    public function getMerchantUserCurrent(): MerchantInterface
    {
        return $this->get(MerchantResolver::class)->getMerchantUser($this->getUserCurrent());
    }

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

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

    public function getSectionCurrentVisited(): ?SectionInterface
    {
        return $this->get(SectionResolver::class)->getCurrent(false, true);
    }

    public function isOutOfSection()
    {
        return $this->get(SectionResolver::class)->isOutOfSection();
    }

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

    public function getCartCurrent(): OrderShopInterface
    {
        return $this->getOrderShopContainer()->getBuilder()->createIfNotExist(
                $this->getSectionCurrent(),
                $this->getUserCurrent(),
                $this->getVisitorCurrent(),
                true
        );
    }

    public function getCartCurrentVisited(): OrderShopInterface
    {
        return $this->getOrderShopContainer()->getBuilder()->createIfNotExist(
                $this->getSectionCurrentVisited(),
                $this->getUserCurrent(),
                $this->getVisitorCurrent(),
                true
        );
    }

    public function getPriceSolver(): PriceSolver
    {
        return $this->get(PriceSolver::class);
    }

    public function getOrderShopContainer(): OrderShopContainer
    {
        return $this->get(OrderShopContainer::class);
    }

    public function getAddressContainer(): AddressContainer
    {
        return $this->get(AddressContainer::class);
    }

    public function getTaxRateContainer(): TaxRateContainer
    {
        return $this->get(TaxRateContainer::class);
    }

    public function getUnitContainer(): UnitContainer
    {
        return $this->get(UnitContainer::class);
    }

    public function getCreditHistoryContainer(): CreditHistoryContainer
    {
        return $this->get(CreditHistoryContainer::class);
    }

    public function getDocumentContainer(): DocumentContainer
    {
        return $this->get(DocumentContainer::class);
    }

    public function getMerchantContainer(): MerchantContainer
    {
        return $this->get(MerchantContainer::class);
    }

    public function getOrderPaymentContainer(): OrderPaymentContainer
    {
        return $this->get(OrderPaymentContainer::class);
    }

    public function getOrderProductContainer(): OrderProductContainer
    {
        return $this->get(OrderProductContainer::class);
    }

    public function getOrderProductReductionCatalogContainer(): OrderProductReductionCatalogContainer
    {
        return $this->get(OrderProductReductionCatalogContainer::class);
    }

    public function getOrderProductRefundContainer(): OrderProductRefundContainer
    {
        return $this->get(OrderProductRefundContainer::class);
    }

    public function getOrderReductionCartContainer(): OrderReductionCartContainer
    {
        return $this->get(OrderReductionCartContainer::class);
    }

    public function getOrderReductionCreditContainer(): OrderReductionCreditContainer
    {
        return $this->get(OrderReductionCreditContainer::class);
    }

    public function getOrderRefundContainer(): OrderRefundContainer
    {
        return $this->get(OrderRefundContainer::class);
    }

    public function getOrderStatusContainer(): OrderStatusContainer
    {
        return $this->get(OrderStatusContainer::class);
    }

    public function getOrderStatusHistoryContainer(): OrderStatusHistoryContainer
    {
        return $this->get(OrderStatusHistoryContainer::class);
    }

    public function getPointSaleContainer(): PointSaleContainer
    {
        return $this->get(PointSaleContainer::class);
    }

    public function getProductCategoryContainer(): ProductCategoryContainer
    {
        return $this->get(ProductCategoryContainer::class);
    }

    public function getProductContainer(): ProductContainer
    {
        return $this->get(ProductContainer::class);
    }

    public function getProductFamilyContainer(): ProductFamilyContainer
    {
        return $this->get(ProductFamilyContainer::class);
    }

    public function getReductionCartContainer(): ReductionCartContainer
    {
        return $this->get(ReductionCartContainer::class);
    }

    public function getReductionCatalogContainer(): ReductionCatalogContainer
    {
        return $this->get(ReductionCatalogContainer::class);
    }

    public function getReductionCreditContainer(): ReductionCreditContainer
    {
        return $this->get(ReductionCreditContainer::class);
    }

    public function getOpeningContainer(): OpeningContainer
    {
        return $this->get(OpeningContainer::class);
    }

    public function getSectionContainer(): SectionContainer
    {
        return $this->get(SectionContainer::class);
    }

    public function getMerchantSettingContainer(): MerchantSettingContainer
    {
        return $this->get(MerchantSettingContainer::class);
    }

    public function getSectionSettingContainer(): SectionSettingContainer
    {
        return $this->get(SectionSettingContainer::class);
    }

    public function getUserMerchantContainer(): UserMerchantContainer
    {
        return $this->get(UserMerchantContainer::class);
    }

    public function getUserPointSaleContainer(): UserPointSaleContainer
    {
        return $this->get(UserPointSaleContainer::class);
    }

    public function getVisitorContainer(): VisitorContainer
    {
        return $this->get(VisitorContainer::class);
    }

    public function getQualityLabelContainer(): QualityLabelContainer
    {
        return $this->get(QualityLabelContainer::class);
    }
}