<?php

/**
 * Matomo - free/libre analytics platform
 *
 * @link    https://matomo.org
 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 */
namespace Piwik\Plugins\UserCountryMap;

use Exception;
use Piwik\API\Request;
use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Piwik;
use Piwik\Site;
use Piwik\Translation\Translator;
use Piwik\View;
require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/functions.php';
class Controller extends \Piwik\Plugin\Controller
{
    // By default plot up to the last 3 days of visitors on the map, for low traffic sites
    public const REAL_TIME_WINDOW = 'last3';
    /**
     * @var Translator
     */
    private $translator;
    public function __construct(Translator $translator)
    {
        $this->translator = $translator;
        parent::__construct();
    }
    public function visitorMap($fetch = \false, $segmentOverride = \false)
    {
        $this->checkUserCountryPluginEnabled();
        $this->checkSitePermission();
        Piwik::checkUserHasViewAccess($this->idSite);
        $period = Common::getRequestVar('period');
        $date = Common::getRequestVar('date');
        if (!empty($segmentOverride)) {
            $segment = $segmentOverride;
        } else {
            $segment = Request::getRawSegmentFromRequest();
            if (empty($segment)) {
                $segment = '';
            }
        }
        $token_auth = Piwik::getCurrentUserTokenAuth();
        $view = new View('@UserCountryMap/visitorMap');
        // request visits summary
        $request = new Request(['method' => 'VisitsSummary.get', 'format' => 'json', 'idSite' => $this->idSite, 'period' => $period, 'date' => $date, 'segment' => $segment, 'token_auth' => $token_auth, 'filter_limit' => -1]);
        $config = [];
        $config['visitsSummary'] = json_decode($request->process(), \true);
        $config['countryDataUrl'] = $this->report('UserCountry', 'getCountry', $this->idSite, $period, $date, $token_auth, \false, $segment);
        $config['regionDataUrl'] = $this->report('UserCountry', 'getRegion', $this->idSite, $period, $date, $token_auth, \true, $segment);
        $config['cityDataUrl'] = $this->report('UserCountry', 'getCity', $this->idSite, $period, $date, $token_auth, \true, $segment);
        $config['countrySummaryUrl'] = $this->getApiRequestUrl('VisitsSummary', 'get', $this->idSite, $period, $date, $token_auth, \true, $segment);
        $view->defaultMetric = array_key_exists('nb_uniq_visitors', $config['visitsSummary'] ?? []) ? 'nb_uniq_visitors' : 'nb_visits';
        $noVisitTranslation = $this->translator->translate('UserCountryMap_NoVisit');
        // some translations containing metric number
        $translations = ['nb_visits' => $this->translator->translate('General_NVisits'), 'no_visit' => $noVisitTranslation, 'nb_actions' => $this->translator->translate('VisitsSummary_NbActionsDescription'), 'nb_actions_per_visit' => $this->translator->translate('VisitsSummary_NbActionsPerVisit'), 'bounce_rate' => $this->translator->translate('VisitsSummary_NbVisitsBounced'), 'avg_time_on_site' => $this->translator->translate('VisitsSummary_AverageVisitDuration'), 'and_n_others' => $this->translator->translate('UserCountryMap_AndNOthers'), 'nb_uniq_visitors' => $this->translator->translate('General_NUniqueVisitors'), 'nb_users' => $this->translator->translate('VisitsSummary_NbUsers')];
        foreach ($translations as &$translation) {
            if (\false === strpos($translation, '%s') && $translation !== $noVisitTranslation) {
                $translation = '%s ' . $translation;
            }
        }
        $translations['one_visit'] = $this->translator->translate('General_OneVisit');
        $translations['no_data'] = $this->translator->translate('CoreHome_ThereIsNoDataForThisReport');
        $view->localeJSON = json_encode($translations);
        $view->reqParamsJSON = $this->getEnrichedRequest($params = ['period' => $period, 'idSite' => $this->idSite, 'date' => $date, 'segment' => $segment, 'token_auth' => $token_auth, 'enable_filter_excludelowpop' => 1, 'filter_excludelowpop_value' => -1]);
        $view->metrics = $config['metrics'] = $this->getMetrics($this->idSite, $period, $date, $token_auth);
        $config['svgBasePath'] = 'plugins/UserCountryMap/svg/';
        $config['mapCssPath'] = 'plugins/UserCountryMap/stylesheets/map.css';
        $view->config = json_encode($config);
        $view->noData = empty($config['visitsSummary']['nb_visits']);
        $countriesByIso = [];
        $regionDataProvider = StaticContainer::get('Piwik\\Intl\\Data\\Provider\\RegionDataProvider');
        $countries = array_keys($regionDataProvider->getCountryList());
        foreach ($countries as $country) {
            $countriesByIso[strtoupper($country)] = Piwik::translate('Intl_Country_' . strtoupper($country));
        }
        $view->countriesByIso = $countriesByIso;
        $view->continents = ['AF' => \Piwik\Plugins\UserCountry\continentTranslate('afr'), 'AS' => \Piwik\Plugins\UserCountry\continentTranslate('asi'), 'EU' => \Piwik\Plugins\UserCountry\continentTranslate('eur'), 'NA' => \Piwik\Plugins\UserCountry\continentTranslate('amn'), 'OC' => \Piwik\Plugins\UserCountry\continentTranslate('oce'), 'SA' => \Piwik\Plugins\UserCountry\continentTranslate('ams')];
        return $view->render();
    }
    /**
     * Used to build the report Visitor > Real time map
     */
    public function realtimeWorldMap()
    {
        return $this->realtimeMap($standalone = \true);
    }
    /**
     * @param bool $standalone When set to true, the Top controls will be hidden to provide better full screen view
     * @param bool $fetch
     * @param bool|string $segmentOverride
     *
     * @return string
     */
    public function realtimeMap($standalone = \false, $fetch = \false, $segmentOverride = \false)
    {
        $this->checkUserCountryPluginEnabled();
        $this->checkSitePermission();
        Piwik::checkUserHasViewAccess($this->idSite);
        $token_auth = Piwik::getCurrentUserTokenAuth();
        $view = new View('@UserCountryMap/realtimeMap');
        $view->mapIsStandaloneNotWidget = !(bool) Common::getRequestVar('widget', $standalone, 'int');
        $view->metrics = $this->getMetrics($this->idSite, 'range', self::REAL_TIME_WINDOW, $token_auth);
        $view->defaultMetric = 'nb_visits';
        $liveRefreshAfterMs = (int) Config::getInstance()->General['live_widget_refresh_after_seconds'] * 1000;
        $goals = Request::processRequest('Goals.getGoals', ['idSite' => $this->idSite, 'filter_limit' => '-1'], $default = []);
        $site = new Site($this->idSite);
        $hasGoals = !empty($goals) || $site->isEcommerceEnabled();
        // maximum number of visits to be displayed in the map
        $maxVisits = Common::getRequestVar('filter_limit', 100, 'int');
        // some translations
        $locale = ['nb_actions' => $this->translator->translate('VisitsSummary_NbActionsDescription'), 'local_time' => $this->translator->translate('VisitTime_ColumnLocalTime'), 'from' => $this->translator->translate('General_FromReferrer'), 'seconds' => $this->translator->translate('Intl_Seconds'), 'seconds_ago' => $this->translator->translate('UserCountryMap_SecondsAgo'), 'minutes' => $this->translator->translate('Intl_Minutes'), 'minutes_ago' => $this->translator->translate('UserCountryMap_MinutesAgo'), 'hours' => $this->translator->translate('Intl_Hours'), 'hours_ago' => $this->translator->translate('UserCountryMap_HoursAgo'), 'days_ago' => $this->translator->translate('UserCountryMap_DaysAgo'), 'actions' => $this->translator->translate('Transitions_NumPageviews'), 'searches' => $this->translator->translate('UserCountryMap_Searches'), 'goal_conversions' => $this->translator->translate('UserCountryMap_GoalConversions')];
        $segment = ($segmentOverride ?: Request::getRawSegmentFromRequest()) ?: '';
        $params = ['period' => 'range', 'idSite' => $this->idSite, 'segment' => $segment, 'token_auth' => $token_auth];
        $realtimeWindow = Common::getRequestVar('realtimeWindow', self::REAL_TIME_WINDOW, 'string');
        if ($realtimeWindow != 'false') {
            // handle special value
            $params['date'] = $realtimeWindow;
        }
        $reqParams = $this->getEnrichedRequest($params, $encode = \false);
        $view->config = ['metrics' => [], 'svgBasePath' => 'plugins/UserCountryMap/svg/', 'liveRefreshAfterMs' => $liveRefreshAfterMs, '_' => $locale, 'reqParams' => $reqParams, 'siteHasGoals' => $hasGoals, 'maxVisits' => $maxVisits, 'changeVisitAlpha' => Common::getRequestVar('changeVisitAlpha', \true, 'int'), 'removeOldVisits' => Common::getRequestVar('removeOldVisits', \true, 'int'), 'showFooterMessage' => Common::getRequestVar('showFooterMessage', \true, 'int'), 'showDateTime' => Common::getRequestVar('showDateTime', \true, 'int'), 'doNotRefreshVisits' => Common::getRequestVar('doNotRefreshVisits', \false, 'int'), 'enableAnimation' => Common::getRequestVar('enableAnimation', \true, 'int'), 'forceNowValue' => Common::getRequestVar('forceNowValue', \false, 'int')];
        return $view->render();
    }
    private function getEnrichedRequest($params, $encode = \true)
    {
        $params['format'] = 'json';
        $params['showRawMetrics'] = 1;
        if (empty($params['segment'])) {
            $segment = Request::getRawSegmentFromRequest();
            if (!empty($segment)) {
                $params['segment'] = $segment;
            }
        }
        if (!empty($params['segment'])) {
            $params['segment'] = urldecode($params['segment']);
        }
        if ($encode) {
            $params = json_encode($params);
        }
        return $params;
    }
    private function checkUserCountryPluginEnabled()
    {
        if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated('UserCountry')) {
            throw new Exception($this->translator->translate('General_Required', 'Plugin UserCountry'));
        }
    }
    private function getMetrics($idSite, $period, $date,
#[\SensitiveParameter]
$token_auth)
    {
        $request = new Request(['method' => 'API.getMetadata', 'format' => 'json', 'apiModule' => 'UserCountry', 'apiAction' => 'getCountry', 'idSite' => $idSite, 'period' => $period, 'date' => $date, 'token_auth' => $token_auth, 'filter_limit' => -1]);
        $metaData = json_decode($request->process(), \true);
        $metrics = [];
        if (!empty($metaData[0]['metrics']) && is_array($metaData[0]['metrics'])) {
            foreach ($metaData[0]['metrics'] as $id => $val) {
                $metrics[] = [$id, $val];
            }
        }
        if (!empty($metaData[0]['processedMetrics']) && is_array($metaData[0]['processedMetrics'])) {
            foreach ($metaData[0]['processedMetrics'] as $id => $val) {
                $metrics[] = [$id, $val];
            }
        }
        return $metrics;
    }
    private function getApiRequestUrl($module, $action, $idSite, $period, $date,
#[\SensitiveParameter]
$token_auth, $filter_by_country = \false, $segmentOverride = \false)
    {
        // use processed reports
        $url = "?module=" . $module . "&method=" . $module . "." . $action . "&format=JSON" . "&idSite=" . $idSite . "&period=" . $period . "&date=" . $date . "&token_auth=" . $token_auth . "&segment=" . ($segmentOverride ?: Request::getRawSegmentFromRequest()) . "&enable_filter_excludelowpop=1" . "&showRawMetrics=1";
        if ($filter_by_country) {
            $url .= "&filter_column=country" . "&filter_sort_column=nb_visits" . "&filter_limit=-1" . "&filter_pattern=";
        } else {
            $url .= "&filter_limit=-1";
        }
        return $url;
    }
    private function report($module, $action, $idSite, $period, $date,
#[\SensitiveParameter]
$token_auth, $filter_by_country = \false, $segmentOverride = \false)
    {
        return $this->getApiRequestUrl('API', 'getProcessedReport&apiModule=' . $module . '&apiAction=' . $action, $idSite, $period, $date, $token_auth, $filter_by_country, $segmentOverride);
    }
}
