<?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\Subscribers;

use Shopware\Models\User\User;
use Shopware\Plugins\ViisonCommon\Classes\Subscribers\Base;

// phpcs:ignore VIISON.Classes.AbstractClassName -- cannot change name to keep backwards compatiblity
abstract class PickwareAppConfig extends Base
{
    /**
     * The name of the event, which must be fired to collect configuration for Pickware apps.
     */
    const EVENT_COLLECT_PICKWARE_APP_CONFIG = 'Shopware_Plugins_ViisonPickware_CollectPickwareAppConfig';

    /**
     * The name of the event, which must be fired to collect all ACL privileges required for using Pickware apps.
     */
    const EVENT_COLLECT_REQUIRED_ACL_PRIVILEGES = 'Shopware_Plugins_ViisonPickware_CollectRequiredACLPrivileges';

    /**
     * The name of the event, which must be fired to collect the custom document types that shall be available in the apps.
     */
    const EVENT_COLLECT_CUSTOM_DOCUMENT_TYPES = 'Shopware_Plugins_ViisonPickware_CollectCustomDocumentTypes';

    /**
     * The name of the event, which must be fired to collect the names and versions of installed Pickware plugins.
     */
    const EVENT_COLLECT_PICKWARE_PLUGIN_VERSIONS = 'Shopware_Plugins_ViisonPickware_CollectPickwarePluginVersions';

    /**
     * Key name for the Pickware ACL config field.
     */
    const APP_ACL_CONFIG_KEY = 'appAcl';

    /**
     * @var string $pluginName
     */
    private $pluginName;

    /**
     * @var string $pluginDisplayName
     */
    private $pluginDisplayName;

    /**
     * @var string $pluginVersion
     */
    private $pluginVersion;

    /**
     * @param \Shopware_Components_Plugin_Bootstrap $pluginBootstrap
     */
    public function __construct(\Shopware_Components_Plugin_Bootstrap $pluginBootstrap)
    {
        parent::__construct($pluginBootstrap);

        $this->pluginName = $pluginBootstrap->getName();
        $this->pluginDisplayName = $pluginBootstrap->getLabel();
        $this->pluginVersion = $pluginBootstrap->getVersion();
    }

    /**
     * @see \Shopware\Plugins\ViisonCommon\Classes\Subscribers\Base::getSubscribedEvents()
     */
    public static function getSubscribedEvents()
    {
        return [
            static::EVENT_COLLECT_PICKWARE_APP_CONFIG => 'onCollectPickwareAppConfig',
            static::EVENT_COLLECT_REQUIRED_ACL_PRIVILEGES => 'onCollectRequiredACLPrivileges',
            static::EVENT_COLLECT_CUSTOM_DOCUMENT_TYPES => 'onCollectCustomDocumentTypes',
            static::EVENT_COLLECT_PICKWARE_PLUGIN_VERSIONS => 'onCollectPickwarePluginVersions',
        ];
    }

    /**
     * Modifies the given config for the Pickware app with the given name and returns the
     * modified config.
     *
     * @param array $config
     * @param string $appName
     * @return array
     */
    abstract public function updateConfig($config, $appName);

    /**
     * Returns an array containing the ACL resources and respective privileges that are required
     * by the API resources used by the app with the given name.
     *
     * @param string $appName
     * @return array
     */
    abstract public function getRequiredACLPrivileges($appName);

    /**
     * Uses the abstract method 'updateConfig()' to modify the current config based on the passed
     * app name and writes it back to the event args.
     *
     * @param \Enlight_Event_EventArgs $args
     */
    public function onCollectPickwareAppConfig(\Enlight_Event_EventArgs $args)
    {
        $config = $this->updateConfig(
            $args->getReturn(),
            $args->get('appName')
        );

        if ($args->get('user')) {
            $result = $this->collectPickwareAclRules($args->get('appName'), $args->get('user'));
            if ($result) {
                $config[self::APP_ACL_CONFIG_KEY] = $result;
            }
        }

        $args->setReturn($config);
    }

    /**
     * @param string $appName
     * @param User $user
     * @return array
     */
    public function collectPickwareAclRules($appName, User $user)
    {
        return [];
    }

    /**
     * Uses the abstract method 'getRequiredACLPrivileges()' to get the required ACL privileges
     * based on the passed app name and writes it back to the event args.
     *
     * @param \Enlight_Event_EventArgs $args
     */
    public function onCollectRequiredACLPrivileges(\Enlight_Event_EventArgs $args)
    {
        return $this->getRequiredACLPrivileges(
            $args->get('appName')
        );
    }

    /**
     * Returns either an ArrayCollection of Shopware\Plugins\ViisonPickwareCommon\Structs\CustomDocumentType instances
     * of null (null by default). Override this method in the implementing subscriber, to make custom document types available
     * for printer configuration in the Pickware apps.
     *
     * @param \Enlight_Event_EventArgs $args
     * @return ArrayCollection|null
     */
    public function onCollectCustomDocumentTypes(\Enlight_Event_EventArgs $args)
    {
        return null;
    }

    /**
     * Adds the 'pluginName' and 'pluginVersion' as a new key/value pair to the already collected
     * plugin versions.
     *
     * @param \Enlight_Event_EventArgs $args
     */
    public function onCollectPickwarePluginVersions(\Enlight_Event_EventArgs $args)
    {
        $pluginVersions = $args->getReturn();
        $pluginVersions[$this->pluginName] = [
            'label' => $this->pluginDisplayName,
            'version' => $this->pluginVersion,
        ];
        $args->setReturn($pluginVersions);
    }
}
