<?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\QueryComponentArrayCoding\FieldDescriptorQueryComponentArrayCoder;
use Shopware\Plugins\ViisonPickwareMobile\Components\QueryComponentArrayCoding\QueryComponentArrayDecodingPreprocessor;

class AttributeFieldQueryComponentArrayDecodingPreprocessor implements QueryComponentArrayDecodingPreprocessor
{
    /**
     * @var string The prefix added to all attribute fields to distinguish them from fields of the respective
     *      "main" table.
     */
    const ATTRIBUTE_FIELD_PREFIX = '__attribute#';

    /**
     * @var array An associative array used for mapping "main" table names to their respective attribute table names.
     */
    const ATTRIBUTE_TABLE_NAMES = [
        's_articles_details' => 's_articles_attributes',
        's_order' => 's_order_attributes',
        's_order_billingaddress' => 's_order_billingaddress_attributes',
        's_order_details' => 's_order_details_attributes',
        's_order_shippingaddress' => 's_order_shippingaddress_attributes',
        's_user' => 's_user_attributes',
    ];

    /**
     * {@inheritdoc}
     *
     * Matches any field descriptor components that select an attribute field and changes the component data to select
     * the same field of the respective attribute table instead.
     */
    public function process(array $arrayData)
    {
        $componentDataMatches = (
            isset($arrayData['type'])
            && $arrayData['type'] === FieldDescriptorQueryComponentArrayCoder::CODABLE_TYPE
            // Note: Prior to PHP 7 `isset()` cannot be used with a const array access expression, which is why we need
            // to use `!== null` instead!
            && self::ATTRIBUTE_TABLE_NAMES[$arrayData['tableName']] !== null
            && self::isAttributeField($arrayData['fieldName'])
        );
        if ($componentDataMatches) {
            $arrayData['tableName'] = self::ATTRIBUTE_TABLE_NAMES[$arrayData['tableName']];
            $arrayData['fieldName'] = self::trimAttributePrefix($arrayData['fieldName']);
        }

        return $arrayData;
    }

    /**
     * @param string $fieldName
     * @return boolean
     */
    public static function isAttributeField($fieldName)
    {
        return mb_strpos($fieldName, self::ATTRIBUTE_FIELD_PREFIX) === 0;
    }

    /**
     * @param string $fieldName
     * @return string
     */
    public static function trimAttributePrefix($fieldName)
    {
        return mb_substr($fieldName, mb_strlen(self::ATTRIBUTE_FIELD_PREFIX));
    }
}
