<?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.

use Doctrine\DBAL\DBALException;
use Doctrine\ORM\Query;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Shopware\CustomModels\ViisonPickwareERP\ItemProperty\ItemProperty;
use Shopware\Plugins\ViisonCommon\Controllers\ViisonCommonBaseController;

class Shopware_Controllers_Backend_ViisonPickwareCommonArticlePropertyTypes extends ViisonCommonBaseController
{
    /**
     * Responds a filtered, sorted, paginated list of property types.
     */
    public function getPropertyTypeListAction()
    {
        $start = $this->Request()->getParam('start');
        $limit = $this->Request()->getParam('limit');
        $filter = $this->Request()->getParam('filter', []);
        $orderBy = $this->Request()->getParam(
            'sort',
            [
                [
                    'property' => 'type.id',
                    'order' => 'ASC',
                ],
            ]
        );

        // Prepare query
        $builder = $this->get('models')->createQueryBuilder();
        $builder
            ->select('type')
            ->from(ItemProperty::class, 'type')
            ->setAlias('type')
            ->addFilter($filter)
            ->addOrderBy($orderBy);
        if ($start !== null) {
            $builder->setFirstResult($start);
        }
        if ($limit !== null) {
            $builder->setMaxResults($limit);
        }

        // Get paginated results
        $query = $builder->getQuery();
        $query->setHydrationMode(Query::HYDRATE_ARRAY);
        $paginator = new Paginator($query);
        $total = $paginator->count();
        $result = $paginator->getIterator()->getArrayCopy();

        $this->View()->assign([
            'success' => true,
            'data' => $result,
            'total' => $total,
        ]);
    }

    /**
     * Creates new property types for each POSTed data entry.
     *
     * @throws DBALException
     */
    public function createPropertyTypesAction()
    {
        // Create a type for each given data array
        $data = $this->Request()->getParam('data');
        $newTypes = [];
        foreach ($data as $typeData) {
            $type = new ItemProperty();
            $type->fromArray($typeData);
            $this->get('models')->persist($type);
            $newTypes[] = $type;
        }
        try {
            $this->get('models')->flush($newTypes);
        } catch (DBALException $e) {
            // 23000 is code for duplicate entry
            if ($e->getPrevious()->getCode() !== '23000') {
                throw $e;
            }
            $this->View()->assign([
                'success' => false,
                'message' => $this->get('snippets')->getNamespace('backend/viison_pickware_common_article_property_types/main')->get('controller/error/duplicate_property_type_name'),
            ]);

            return;
        }

        // Set a filter parameter using the IDs of the newly created types and add the data of the created types to the
        // response
        $this->Request()->setParam('filter', [
            [
                'property' => 'type.id',
                'expression' => 'IN',
                'value' => array_map(
                    function (ItemProperty $type) {
                        return $type->getId();
                    },
                    $newTypes
                ),
            ],
        ]);
        $this->getPropertyTypeListAction();
    }

    /**
     * Finds the property type entities for all POSTed data entries and updates their values.
     *
     * @throws DBALException
     */
    public function updatePropertyTypesAction()
    {
        // Update all given types
        $data = $this->Request()->getParam('data');
        $updatedTypes = [];
        foreach ($data as $typeData) {
            $type = $this->get('models')->find(ItemProperty::class, $typeData['id']);
            if ($type) {
                $type->fromArray($typeData);
                $updatedTypes[] = $type;
            }
        }
        try {
            $this->get('models')->flush($updatedTypes);
        } catch (DBALException $e) {
            // 23000 is code for duplicate entry
            if ($e->getPrevious()->getCode() !== '23000') {
                throw $e;
            }
            $this->View()->assign([
                'success' => false,
                'message' => $this->get('snippets')->getNamespace('backend/viison_pickware_common_article_property_types/main')->get('controller/error/duplicate_property_type_name'),
            ]);

            return;
        }

        // Respond with the updated types
        $this->getPropertyTypeListAction();
    }

    /**
     * Deletes the property type entities that correspond to the POSTed data entries.
     */
    public function deletePropertyTypesAction()
    {
        // Remove all given types
        $data = $this->Request()->getParam('data');
        foreach ($data as $typeData) {
            $type = $this->get('models')->find(ItemProperty::class, $typeData['id']);
            if ($type) {
                $this->get('models')->remove($type);
                $this->get('models')->flush($type);
            }
        }

        // Respond with the updated types
        $this->getPropertyTypeListAction();
    }
}
