<?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\ViisonPickwareCommon\Classes\ApiRequestCompatibility\Layers;

use Shopware\Plugins\ViisonPickwareCommon\Classes\ApiRequestCompatibility\Layer;

class Variants20181216 extends Layer
{
    /**
     * @inheritdoc
     */
    public function getVersion()
    {
        return '2018-12-16';
    }

    /**
     * Replaces several special filters with respective filter elements that utilize nested filters as supported by the
     * main action.
     *
     * pre GET /api/variants
     */
    public function preIndexAction()
    {
        $filter = $this->request->getParam('filter', []);

        // Remove the deprecated `pickwareCompleteVariantName` filter element, if set
        foreach ($filter as $key => $filterElement) {
            if ($filterElement['property'] === 'pickwareCompleteVariantName') {
                unset($filter[$key]);
            }
        }

        // Unroll any filter elements that use the `CSV` expression
        $unrolledFilter = [];
        foreach ($filter as $filterElement) {
            if (isset($filterElement['expression']) && mb_strtolower($filterElement['expression']) === 'csv') {
                $unrolledFilter[] = $this->unrollCSVFilter($filterElement);
            } else {
                $unrolledFilter[] = $filterElement;
            }
        }
        $filter = $unrolledFilter;

        // Convert any grouped filters to the new nested filter structure
        $groupedFilter = $this->request->getParam('groupedFilter', []);
        foreach ($groupedFilter as $filterElement) {
            $isDisjunction = array_reduce(
                $filterElement['filter'],
                function ($carry, array $item) {
                    return $carry && $item['operator'] !== null;
                },
                true
            );
            $filter[] = [
                'operator' => $filterElement['operator'],
                'disjunction' => $isDisjunction,
                'children' => $filterElement['filter'],
            ];
        }

        // Add a filter that excludes any ESD products
        $filter[] = [
            'property' => 'esd.id',
            'value' => null,
        ];

        $this->request->setParam('filter', $filter);
    }

    /**
     * 'Unrolls' a 'CSV' filter array, by creating four single filters for matching the possible positions of a value in
     * a CSV string:
     *  - only one value (no commas)
     *  - 1st value (trailing comma)
     *  - 2nd to (n-1)st value (leading and trailing comma)
     *  - n-th value (leading comma)
     */
    protected function unrollCSVFilter(array $filter)
    {
        return [
            'operator' => $filter['operator'],
            'disjunction' => true,
            'children' => [
                // Only one value
                [
                    'property' => $filter['property'],
                    'value' => $filter['value'],
                ],
                // 1st value
                [
                    'property' => $filter['property'],
                    'value' => $filter['value'] . ',%',
                ],
                // 2nd to (n-1]st value
                [
                    'property' => $filter['property'],
                    'value' => '%,' . $filter['value'] . ',%',
                ],
                // n-th value
                [
                    'property' => $filter['property'],
                    'value' => '%,' . $filter['value'],
                ],
            ],
        ];
    }
}
