<?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\ViisonCommon\Commands;

use Shopware\Commands\ShopwareCommand;
use Shopware\Models\Plugin\Plugin;
use Shopware\Plugins\ViisonCommon\Components\PluginConfigImporterService;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * A command to read in the shopware plugin configuration from a file and apply it.
 * The expected file yaml file structure is
 * configuration:
 *      key1: value1
 *      key2: value2
 */
class PluginConfigImport extends ShopwareCommand
{
    /**
     * Add a default config to be loaded for all automated tools
     */
    const DEFAULT_CONFIG_FILE_PATH = 'dev/config.yaml';

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName('viison:plugin:config:import')
            ->setDescription('Imports a predefined configuration of a VIISON plugin')
            ->addArgument(
                'plugin',
                InputArgument::REQUIRED,
                'Name of the plugin to load the configuration for'
            )
            ->addOption(
                'path',
                null,
                InputOption::VALUE_OPTIONAL,
                'Path to the configuration file'
            )
            ->addOption(
                'shopId',
                null,
                InputOption::VALUE_OPTIONAL,
                'Id of the subshop to set the configuration for'
            );
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $plugin = $this->getPlugin($input);

        /** @var PluginConfigImporterService $configImporter */
        $configImporter = $this->container->get('viison_common.plugin_config_importer');
        $configImporter->importConfigForPlugin(
            $plugin,
            $this->getPathToConfigFile($input, $plugin),
            $this->getShop($input)
        );

        $output->writeln('The plugin\'s configuration has been loaded');
    }

    /**
     * Loads the model entity of the plugin, which is specified by its name via
     * the command line and checks that the plugin is installed and active.
     *
     * @param InputInterface $input
     * @return Plugin
     * @throws \Exception if the plugin does not exist or is not active
     */
    private function getPlugin(InputInterface $input)
    {
        $entityManager = $this->container->get('models');

        $pluginName = $input->getArgument('plugin');
        $plugin = $entityManager->getRepository('Shopware\\Models\\Plugin\\Plugin')->findOneBy([
            'name' => $pluginName,
        ]);

        if ($plugin === null) {
            throw new \Exception('The specified plugin does not exist');
        } elseif (!$plugin->getInstalled()) {
            throw new \Exception('The specified plugin is not installed');
        }

        return $plugin;
    }

    /**
     * Returns the path to the config file to be loaded. If no path is specified
     * on the command line the default path will be used.
     *
     * @param InputInterface $input
     * @param Plugin $plugin
     * @return string
     */
    private function getPathToConfigFile(InputInterface $input, Plugin $plugin)
    {
        $path = $input->getOption('path', null);
        if ($path !== null) {
            // Check for absolute path
            return (mb_substr($path, 0, 1) === '/') ? $path : (getcwd() . '/' . $path);
        } else {
            // Use the plugin's default config
            $pluginsNamespace = $this->container->get('plugins')->get($plugin->getNamespace());
            $pluginPath = $pluginsNamespace->get($plugin->getName())->Path();

            return $pluginPath . PluginConfigImport::DEFAULT_CONFIG_FILE_PATH;
        }
    }

    /**
     * Returns the shops the configuration should be used for.
     *
     * @param InputInterface $input
     * @return Shop|null
     * @throws \Exception
     */
    private function getShop(InputInterface $input)
    {
        $shopId = $input->getOption('shopId');
        $shopRepository = $this->container->get('models')->getRepository('Shopware\\Models\\Shop\\Shop');

        if (!$shopId) {
            return $shopRepository->getDefault();
        }

        $shop = $shopRepository->find($shopId);

        if (!$shop) {
            throw new \Exception('The specified shop does not exist');
        }

        return $shop;
    }
}
