<?php
namespace WapplerSystems\Meilisearch\Controller\Backend\Search;

/***************************************************************
 *  Copyright notice
 *
 *  (c) 2013-2015 Ingo Renner <ingo@typo3.org>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
 *  free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  The GNU General Public License can be found at
 *  http://www.gnu.org/copyleft/gpl.html.
 *
 *  This script is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  This copyright notice MUST APPEAR in all copies of the script!
 ***************************************************************/

use WapplerSystems\Meilisearch\ConnectionManager;
use WapplerSystems\Meilisearch\IndexQueue\Queue;
use WapplerSystems\Meilisearch\System\Meilisearch\MeilisearchConnection;
use WapplerSystems\Meilisearch\Util;
use TYPO3\CMS\Backend\Routing\UriBuilder as BackendUriBuilder;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Web\ReferringRequest;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;

/**
 * Index Administration Module
 *
 * @author Ingo Renner <ingo@typo3.org>
 */
class IndexAdministrationModuleController extends AbstractModuleController
{

    /**
     * @var Queue
     */
    protected $indexQueue;

    /**
     * @var ConnectionManager
     */
    protected $meilisearchConnectionManager = null;

    /**
     * @param ConnectionManager $meilisearchConnectionManager
     */
    public function setMeilisearchConnectionManager(ConnectionManager $meilisearchConnectionManager)
    {
        $this->meilisearchConnectionManager = $meilisearchConnectionManager;
    }

    /**
     * Initializes the controller before invoking an action method.
     */
    protected function initializeAction()
    {
        parent::initializeAction();
        $this->indexQueue = GeneralUtility::makeInstance(Queue::class);
        $this->meilisearchConnectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
    }

    /**
     * Index action, shows an overview of available index maintenance operations.
     *
     * @return void
     */
    public function indexAction()
    {
        if ($this->selectedSite === null || empty($this->meilisearchConnectionManager->getConnectionBySite($this->selectedSite))) {
            $this->view->assign('can_not_proceed', true);
        }
    }

    /**
     * Empties the site's indexes.
     *
     * @return void
     */
    public function emptyIndexAction()
    {
        $siteHash = $this->selectedSite->getSiteHash();

        try {
            $affectedCores = [];
            $meilisearchServers = $this->meilisearchConnectionManager->getConnectionBySite($this->selectedSite);
            foreach ($meilisearchServers as $meilisearchServer) {
                $writeService = $meilisearchServer->getWriteService();
                /* @var $meilisearchServer MeilisearchConnection */
                $writeService->deleteByQuery('siteHash:' . $siteHash);
                $writeService->commit(false, false, false);
                $affectedCores[] = $writeService->getPrimaryEndpoint()->getCore();
            }
            $message = LocalizationUtility::translate('meilisearch.backend.index_administration.index_emptied_all', 'Meilisearch', [$this->selectedSite->getLabel(), implode(', ', $affectedCores)]);
            $this->addFlashMessage($message);
        } catch (\Exception $e) {
            $this->addFlashMessage(LocalizationUtility::translate('meilisearch.backend.index_administration.error.on_empty_index', 'Meilisearch', [$e->__toString()]), '', FlashMessage::ERROR);
        }

        $this->redirect('index');
    }

    /**
     * Empties the Index Queue
     *
     * @return void
     */
    public function clearIndexQueueAction()
    {
        $this->indexQueue->deleteItemsBySite($this->selectedSite);
        $this->addFlashMessage(
            LocalizationUtility::translate('meilisearch.backend.index_administration.success.queue_emptied', 'Meilisearch',
                [$this->selectedSite->getLabel()])
        );
        $this->redirectToReferrerModule();
    }

    /**
     * Reloads the site's Meilisearch cores.
     *
     * @return void
     */
    public function reloadIndexConfigurationAction()
    {
        $coresReloaded = true;
        $reloadedCores = [];
        $meilisearchServers = $this->meilisearchConnectionManager->getConnectionBySite($this->selectedSite);

        foreach ($meilisearchServers as $meilisearchServer) {
            /* @var $meilisearchServer MeilisearchConnection */
            $coreAdmin = $meilisearchServer->getService();
            $coreReloaded = $coreAdmin->reloadCore()->getHttpStatus() === 200;

            $coreName = $coreAdmin->getPrimaryEndpoint()->getCore();
            if (!$coreReloaded) {
                $coresReloaded = false;

                $this->addFlashMessage(
                    'Failed to reload index configuration for core "' . $coreName . '"',
                    '',
                    FlashMessage::ERROR
                );
                break;
            }

            $reloadedCores[] = $coreName;
        }

        if ($coresReloaded) {
            $this->addFlashMessage(
                'Core configuration reloaded (' . implode(', ', $reloadedCores) . ').',
                '',
                FlashMessage::OK
            );
        }

        $this->redirect('index');
    }

    /**
     * Redirects to the referrer module index Action.
     *
     * Fluids <f:form VH can not make urls to other modules properly.
     * The module name/key is not provided in the hidden fields __referrer by bulding form.
     * So this is currently the single way to make it possible.
     *
     * @todo: remove this method if f:form works properly between backend modules.
     */
    protected function redirectToReferrerModule()
    {
        $wasFromQueue = $this->request->hasArgument('fromQueue');
        if (!$wasFromQueue) {
            $this->redirect('index');
            return;
        }

        /* @var BackendUriBuilder $backendUriBuilder */
        $backendUriBuilder = GeneralUtility::makeInstance(BackendUriBuilder::class);

        $parameters =  ['id' => $this->selectedPageUID];
        $referringUri = $backendUriBuilder->buildUriFromRoute('searchbackend_MeilisearchIndexqueue', $parameters);

        $this->redirectToUri($referringUri);
    }
}