<?php
namespace WapplerSystems\Meilisearch\System\Meilisearch\Service;

/***************************************************************
 *  Copyright notice
 *
 *  (c) 2009-2017 Timo Hund <timo.hund@dkd.de>
 *  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 MeiliSearch\Client;
use MeiliSearch\Exceptions\CommunicationException;
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
use WapplerSystems\Meilisearch\System\Logging\MeilisearchLogManager;
use WapplerSystems\Meilisearch\System\Meilisearch\MeilisearchConnection;
use WapplerSystems\Meilisearch\System\Meilisearch\ResponseAdapter;
use WapplerSystems\Meilisearch\Util;
use TYPO3\CMS\Core\Utility\GeneralUtility;

abstract class AbstractMeilisearchService
{

    /**
     * @var TypoScriptConfiguration
     */
    protected $configuration;

    /**
     * @var \WapplerSystems\Meilisearch\System\Logging\MeilisearchLogManager
     */
    protected $logger = null;

    /**
     * @var Client
     */
    protected $client = null;

    /**
     * @var MeilisearchConnection
     */
    protected $meilisearchConnection = null;

    /**
     * MeilisearchReadService constructor.
     */
    public function __construct(MeilisearchConnection $meilisearchConnection, Client $client, $typoScriptConfiguration = null, $logManager = null)
    {
        $this->meilisearchConnection = $meilisearchConnection;
        $this->client = $client;
        $this->configuration = $typoScriptConfiguration ?? Util::getMeilisearchConfiguration();
        $this->logger = $logManager ?? GeneralUtility::makeInstance(MeilisearchLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
    }


    /**
     * Returns the Solarium client
     *
     * @return ?Client
     */
    public function getClient(): ?Client
    {
        return $this->client;
    }

    /**
     * @return MeilisearchConnection
     */
    public function getMeilisearchConnection(): ?MeilisearchConnection
    {
        return $this->meilisearchConnection;
    }

    /**
     *
     */
    public function __toString()
    {

        $siteConfiguration = $this->meilisearchConnection->getSiteConfiguration();
        $strConnection = $siteConfiguration['schema'].$siteConfiguration['host'];

        if (!$this->ping()) return $strConnection;

        return $strConnection . ', ' . implode(',',$this->client->version());
    }



    /**
     * Build the log data and writes the message to the log
     *
     * @param integer $logSeverity
     * @param string $message
     * @param string $url
     * @param ResponseAdapter $meilisearchResponse
     * @param ?\Exception $exception
     * @param string $contentSend
     */
    protected function writeLog($logSeverity, $message, $url, $meilisearchResponse, $exception = null, $contentSend = '')
    {
        $logData = $this->buildLogDataFromResponse($meilisearchResponse, $exception, $url, $contentSend);
        $this->logger->log($logSeverity, $message, $logData);
    }

    /**
     * Parses the meilisearch information to build data for the logger.
     *
     * @param ResponseAdapter $meilisearchResponse
     * @param ?\Exception $e
     * @param string $url
     * @param string $contentSend
     * @return array
     */
    protected function buildLogDataFromResponse(ResponseAdapter $meilisearchResponse, \Exception $e = null, $url = '', $contentSend = '')
    {
        $logData = ['query url' => $url, 'response' => (array)$meilisearchResponse];

        if ($contentSend !== '') {
            $logData['content'] = $contentSend;
        }

        if (!empty($e)) {
            $logData['exception'] = $e->__toString();
            return $logData;
        }
        // trigger data parsing
        // @extensionScannerIgnoreLine
        $meilisearchResponse->response;
        $logData['response data'] = print_r($meilisearchResponse, true);
        return $logData;

    }


    /**
     * @return bool
     */
    public function ping()
    {
        try {
            $health = $this->client->health();
        } catch (CommunicationException $ex) {
            return false;
        }
        return is_array($health) && $health['status'] === 'available';
    }


    /**
     * Returns the current time in milliseconds.
     *
     * @return double
     */
    protected function getMilliseconds()
    {
        return GeneralUtility::milliseconds();
    }


}
