<?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 Shopware\CustomModels\ViisonPickwareCommon\RestApi\RestApiDevice;
use Shopware\Models\Plugin\Plugin;
use Shopware\Plugins\ViisonCommon\Controllers\ViisonCommonBaseController;
use Shopware\Plugins\ViisonPickwareCommon\Classes\Util;

/**
 * Provides the actions (list, update, delete) for the Pickware device management backend app.
 */
class Shopware_Controllers_Backend_ViisonPickwareCommonDeviceManagement extends ViisonCommonBaseController
{
    /**
     * Sets the ACL permissions.
     */
    public function initAcl()
    {
        $this->addAclPermission('getAppSupportInfo', 'read', 'You\'re not allowed to see the Pickware device limits.');
        $this->addAclPermission('getDeviceList', 'read', 'You\'re not allowed to see the Pickware device list.');
        $this->addAclPermission('updateDevices', 'update', 'You\'re not allowed to update Pickware devices.');
        $this->addAclPermission('deleteDevices', 'delete', 'You\'re not allowed to delete Pickware devices.');
    }

    /**
     * Responds with the app support info, incl. the names of supported Pickware apps and respective device limits.
     */
    public function getAppSupportInfoAction()
    {
        $appSupportInfo = $this->get('viison_pickware_common.device_licensing')->getAppSupportInfo();

        // Add the plugin labels to the app support info
        $plugins = $this->get('models')->getRepository(Plugin::class)->findBy([
            'name' => array_keys($appSupportInfo),
        ]);
        foreach ($plugins as $plugin) {
            $appSupportInfo[$plugin->getName()]['pluginLabel'] = $plugin->getLabel();
        }

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

    /**
     * Responds with an array of devices.
     */
    public function getDeviceListAction()
    {
        // Fetch all devices from the list
        $builder = $this->get('models')->createQueryBuilder();
        $builder
            ->select('device')
            ->from(RestApiDevice::class, 'device')
            ->addOrderBy('device.appName')
            ->addOrderBy('device.name');
        $devices = $builder->getQuery()->getArrayResult();

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

    /**
     * Uses the posted device data to update the 'name' and 'confirmed' fields of the corresponding devices.
     */
    public function updateDevicesAction()
    {
        // Get request data
        $data = $this->Request()->getParam('data');
        if (!$data) {
            $this->View()->assign([
                'success' => false,
                'message' => 'Missing data',
            ]);
            $this->Response()->setHttpResponseCode(400);

            return;
        }

        // Update every posted device
        $updatedDevices = [];
        foreach ($data as $deviceData) {
            $device = $this->get('models')->find(RestApiDevice::class, $deviceData['id']);
            if (!$device) {
                continue;
            }

            // Update the device using the given data
            $device->setName($deviceData['name']);
            if ($deviceData['confirmed'] === true && !$device->isConfirmed() && $this->get('viison_pickware_common.device_licensing')->isDeviceLimitReached($device->getAppName())) {
                // Device limit already reached
                $this->View()->assign([
                    'success' => false,
                    'message' => 'Cannot confirm device, because the limit is already reached',
                ]);

                return;
            }
            $device->setConfirmed($deviceData['confirmed']);
            $updatedDevices[] = $device;
        }

        // Save changes
        $this->get('models')->flush($updatedDevices);

        $this->View()->success = true;
    }

    /**
     * Uses the posted device data to remove the corresponding devices from the database.
     */
    public function deleteDevicesAction()
    {
        // Get request data
        $data = $this->Request()->getParam('data');
        if (!$data) {
            $this->View()->assign([
                'success' => false,
                'message' => 'Missing data',
            ]);
            $this->Response()->setHttpResponseCode(400);

            return;
        }

        // Delete every posted device
        $deviceIds = array_map(
            function (array $deviceData) {
                return $deviceData['id'];
            },
            $data
        );
        $devices = $this->get('models')->getRepository(RestApiDevice::class)->findBy([
            'id' => $deviceIds,
        ]);
        foreach ($devices as $device) {
            $this->get('models')->remove($device);
        }
        $this->get('models')->flush($devices);

        $this->View()->success = true;
    }
}
