<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonPickwareMobile\Subscribers\Models;

use Shopware\Components\Model\QueryBuilder;
use Shopware\Plugins\ViisonCommon\Classes\Subscribers\Base;
use Shopware\Plugins\ViisonCommon\Classes\Util\Doctrine as ViisonCommonDoctrineUtil;

class OrderSubscriber extends Base
{
    /**
     * @inheritdoc
     */
    public static function getSubscribedEvents()
    {
        return [
            'Shopware\\Models\\Order\\Repository::filterListQuery::before' => 'onBeforeRepositoryFilterListQuery',
            'Shopware\\Models\\Order\\Repository::getBackendOrdersQueryBuilder::after' => 'onAfterGetBackendOrdersQueryBuilder',
        ];
    }

    /**
     * Checks the given filter for the custom
     * 'viisonPickwareMobileWaitingForStock' filter elements. If given, they are removed from the filter parameter and
     * the unrolled filters for these keys are directly added to the $args' query builder.
     *
     * @param \Enlight_Hook_HookArgs $args
     */
    public function onBeforeRepositoryFilterListQuery(\Enlight_Hook_HookArgs $args)
    {
        // Check the a filter
        $filters = $args->filters;
        if (!is_array($filters)) {
            return;
        }

        // Check whether the Pickware stock filter and warehouse are given and enabled
        $stockBasedFilterIndex = -1;
        $pickingAppVisibilityFilterIndex = -1;
        foreach ($filters as $index => $filterElement) {
            if (!is_array($filterElement)) {
                continue;
            }
            switch ($filterElement['property']) {
                case 'viisonPickwareMobileWaitingForStock':
                    $stockBasedFilterIndex = $index;
                    break;
                case 'viisonPickwareMobilePickingAppVisibility':
                    $pickingAppVisibilityFilterIndex = $index;
                    break;
            }
        }

        // Add the custom filters
        /** @var QueryBuilder $builder */
        $builder = $args->builder;
        if ($stockBasedFilterIndex !== -1) {
            // Find all orders that are waiting for stock
            $orderIds = $this->get('viison_pickware_mobile.pick_profile_order_filter_service')->getIdsOfOrdersWaitingWithStockForFilterOfPickProfile(
                $filters[$stockBasedFilterIndex]['value']['pickProfile'],
                $filters[$stockBasedFilterIndex]['value']['warehouse']
            );
            unset($filters[$stockBasedFilterIndex]);

            // Add the unrolled, stock based filter to the query builder
            $builder->andWhere('orders.id IN (:viisonPickwareMobileWaitingForStockOrderIds)');
            $builder->setParameter(
                'viisonPickwareMobileWaitingForStockOrderIds',
                (count($orderIds) > 0) ? $orderIds : -1
            );
        }
        if ($pickingAppVisibilityFilterIndex !== -1) {
            // Find all orders that are visible in the picking app
            $orderIds = $this->get('viison_pickware_mobile.pick_profile_order_filter_service')->getIdsOfOrdersPassingFilterOfPickProfile(
                $filters[$pickingAppVisibilityFilterIndex]['value']['pickProfile'],
                $filters[$pickingAppVisibilityFilterIndex]['value']['warehouse']
            );

            // Add the unrolled, app visibility filter to the query builder
            if ($filters[$pickingAppVisibilityFilterIndex]['value']['isVisibleInPickingApp']) {
                $builder->andWhere('orders.id IN (:viisonPickwareMobileVisibleInPickingAppOrderIds)');
            } else {
                $builder->andWhere('orders.id NOT IN (:viisonPickwareMobileVisibleInPickingAppOrderIds)');
            }
            $builder->setParameter(
                'viisonPickwareMobileVisibleInPickingAppOrderIds',
                (count($orderIds) > 0) ? $orderIds : -1
            );

            unset($filters[$pickingAppVisibilityFilterIndex]);
        }
        $args->filters = $filters;
    }

    /**
     * Shopware < 5.3.0 only!
     *
     * Prior to Shopware v5.2.15 the query builder does not contain a JOIN of the order's attributes ('orders.attribute'),
     * which we use both for custom sort ('onBeforeGetBackendOrdersQueryBuilder()') and filter ('onBeforeRepositoryFilterListQuery()')
     * parameters. Hence we add the JOIN if it is not available in the query builder.
     *
     * @param \Enlight_Hook_HookArgs $args
     */
    public function onAfterGetBackendOrdersQueryBuilder(\Enlight_Hook_HookArgs $args)
    {
        $builder = $args->getReturn();
        if (!ViisonCommonDoctrineUtil::builderHasJoin($builder, 'orders', 'attribute')) {
            $builder->leftJoin('orders.attribute', 'attribute');
        }
    }
}
