<?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\ViisonSetArticles\Classes;

abstract class AbstractPluginPatcher
{
    private $pluginName;
    private $sourceDir;
    private $hookSubDir;
    private $modelManager;

    private $pluginNotFoundResult = [];
    private $directoryNotFoundResult = [];
    private $doPatchSuccessResult = [];
    private $doPatchFailureResult = [];
    private $undoPatchSuccessResult = [];
    private $undoPatchFailureResult = [];

    /**
     * PluginPatcher constructor.
     *
     * @param $pluginName
     * @param $src
     * @param $hookDir
     */
    public function __construct($modelManager, $pluginName, $src, $hookDir)
    {
        $this->modelManager = $modelManager;
        $this->pluginName = $pluginName;
        $this->sourceDir = $src;
        $this->hookSubDir = $hookDir;

        // return statements
        $this->pluginNotFoundResult = [
            'success' => false,
            'message' => 'Ziel-Plugin ' . $this->pluginName . ' ist nicht installiert',
        ];
        $this->directoryNotFoundResult = [
            'success' => false,
            'message' => 'Ziel-Verzeichnis konnte nicht ausgelesen werden.',
        ];
        $this->doPatchSuccessResult = [
            'success' => true,
            'message' => 'Ziel-Plugin ' . $this->pluginName . ' wurde erfolgreich gepatcht.',
        ];
        $this->doPatchFailureResult = [
            'success' => false,
            'message' => 'Ziel-Plugin ' . $this->pluginName . ' konnte nicht gepatcht werden.',
        ];
        $this->undoPatchSuccessResult = [
            'success' => true,
            'message' => 'Patch Dateien ' . $this->pluginName . ' wurde erfolgreich entfernt.',
        ];
        $this->undoPatchFailureResult = [
            'success' => false,
            'message' => 'Patch Dateien ' . $this->pluginName . ' wurden nicht entfernt.',
        ];
    }

    /**
     * Removes patchfiles (e.g. on uninstallation)
     * @return array
     */
    public function undoPatch()
    {
        if (!$this->isPluginInstalled()) {
            return $this->pluginNotFoundResult;
        }

        // Fetch exact target dir. In the patchfile sourceDir should only be ONE folde that was copied upon patching.
        // This foldername is now fetched and looked for in the target directory.
        $directories = glob($this->sourceDir . '/*', GLOB_ONLYDIR);

        if (!$directories || !$directories[0]) {
            return $this->undoPatchFailureResult;
        }

        // Fetch target directory
        $targetDir = $this->getPluginPath() . $this->hookSubDir . '/' . basename($directories[0]);

        // Return if plugin dir could not be found
        if (!$targetDir) {
            return $this->directoryNotFoundResult;
        }

        // Remove all patch files
        $fileRemover = new FileRemover($targetDir);
        if ($fileRemover->remove()) {
            return $this->undoPatchSuccessResult;
        } else {
            return $this->undoPatchFailureResult;
        }
    }

    /**
     * Applies patch: fetches all relevant information and initialize copying files
     * @return bool
     */
    public function doPatch()
    {
        // Return if plugin is not installed
        if (!$this->isPluginInstalled()) {
            return $this->pluginNotFoundResult;
        }

        // Fetch target directory
        $targetDir = $this->getPluginPath() . $this->hookSubDir;

        // Return if plugin dir could not be found
        if (!$targetDir) {
            return $this->directoryNotFoundResult;
        }

        // Copy all files
        $fileMover = new FileMover($this->sourceDir, $targetDir);
        if ($fileMover->copy()) {
            return $this->doPatchSuccessResult;
        } else {
            return $this->doPatchFailureResult;
        }
    }

    /**
     * Checks if the plugin is installed
     *
     * @return mixed
     */
    private function isPluginInstalled()
    {
        $result = $this->modelManager->getRepository('Shopware\\Models\\Plugin\\Plugin')->findOneBy([
            'name' => $this->pluginName,
        ]);
        if (!$result) {
            $result = false;
        } else {
            $result = true;
        }

        return $result;
    }

    /**
     * Fetches the patch to the plugin base dir.
     * E.g. "/var/www/shopware/engine/Shopware/Plugins/Community/Backend/MyPlugin/"
     *
     * @return string|void
     */
    private function getPluginPath()
    {
        $plugin = $this->modelManager->getRepository('Shopware\\Models\\Plugin\\Plugin')->findOneBy([
            'name' => $this->pluginName,
        ]);

        if (!$plugin) {
            return;
        }

        $pluginPath = __DIR__ . '/../../../../' . $plugin->getSource() . '/' . $plugin->getNamespace() . '/' . $plugin->getName();

        return $pluginPath;
    }
}
