<?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\Components\PickingOrderFilter\OrderFilterConditionQueryComponent;

use Shopware\Plugins\ViisonPickwareMobile\Components\QueryBuilder\BooleanCompositionQueryComponent;
use Shopware\Plugins\ViisonPickwareMobile\Components\QueryBuilder\ComparisonQueryComponent;
use Shopware\Plugins\ViisonPickwareMobile\Components\QueryBuilder\ScalarValueQueryComponent;
use Shopware\Plugins\ViisonPickwareMobile\Components\QueryBuilder\UnaryOperationQueryComponent;
use Shopware\Plugins\ViisonPickwareMobile\Components\QueryComponentArrayCoding\FieldDescriptorQueryComponentArrayCoder;
use Shopware\Plugins\ViisonPickwareMobile\Components\QueryComponentArrayCoding\QueryComponentArrayCodingService;
use Shopware\Plugins\ViisonPickwareMobile\Components\QueryComponentArrayCoding\QueryComponentArrayDecodingPreprocessor;
use Shopware\Plugins\ViisonPickwareMobile\Components\QueryComponentArrayCoding\ScalarValueQueryComponentArrayCoder;
use Shopware\Plugins\ViisonPickwareMobile\Components\QueryComponentArrayCoding\UnaryOperationQueryComponentArrayCoder;

class IsEmptyQueryComponentArrayDecodingProprocessor implements QueryComponentArrayDecodingPreprocessor
{
    /**
     * @var string
     */
    const OPERATOR_TYPE_IS_EMPTY = 'is_empty';

    /**
     * @var string
     */
    const OPERATOR_TYPE_IS_NOT_EMPTY = 'is_not_empty';

    /**
     * @var string[]
     */
    const PROCESSABLE_EMPTY_OPERATORS = [
        self::OPERATOR_TYPE_IS_EMPTY,
        self::OPERATOR_TYPE_IS_NOT_EMPTY,
    ];

    /**
     * @var QueryComponentArrayCodingService
     */
    protected $codingService;

    /**
     * @param QueryComponentArrayCodingService $codingService
     */
    public function __construct(QueryComponentArrayCodingService $codingService)
    {
        $this->codingService = $codingService;
    }

    /**
     * {@inheritdoc}
     *
     * Unwraps all `is_empty` and `is_not_empty` operators to test the fields for the correct `NULL` values as well
     * as for empty strings.
     */
    public function process(array $arrayData)
    {
        $componentDataMatches = (
            isset($arrayData['type'])
            && $arrayData['type'] === UnaryOperationQueryComponentArrayCoder::CODABLE_TYPE
            && in_array($arrayData['operator'], self::PROCESSABLE_EMPTY_OPERATORS)
            && $arrayData['leftOperand']['type'] === FieldDescriptorQueryComponentArrayCoder::CODABLE_TYPE
        );
        if (!$componentDataMatches) {
            return $arrayData;
        }

        $leftOperand = $this->codingService->decode($arrayData['leftOperand']);
        switch ($arrayData['operator']) {
            case self::OPERATOR_TYPE_IS_EMPTY:
                $queryComponent = new BooleanCompositionQueryComponent(
                    BooleanCompositionQueryComponent::BOOLEAN_OPERATOR_OR,
                    [
                        new UnaryOperationQueryComponent($leftOperand, 'IS NULL'),
                        new ComparisonQueryComponent($leftOperand, '=', new ScalarValueQueryComponent('')),
                    ]
                );
                break;
            case self::OPERATOR_TYPE_IS_NOT_EMPTY:
                $queryComponent = new BooleanCompositionQueryComponent(
                    BooleanCompositionQueryComponent::BOOLEAN_OPERATOR_AND,
                    [
                        new UnaryOperationQueryComponent($leftOperand, 'IS NOT NULL'),
                        new ComparisonQueryComponent($leftOperand, '!=', new ScalarValueQueryComponent('')),
                    ]
                );
                break;
        }

        return $this->codingService->encode($queryComponent);
    }
}
