<?php

declare(strict_types=1);

namespace Inpsyde\MultilingualPress\Module\LanguageSwitcher;

use Inpsyde\MultilingualPress\Core\Admin\SiteSettingsRepository;
use Inpsyde\MultilingualPress\Flags\Flag\Flag;
use Inpsyde\MultilingualPress\Framework\Api\Translation;
use Inpsyde\MultilingualPress\Framework\Api\Translations;
use Inpsyde\MultilingualPress\Framework\Api\TranslationSearchArgs;
use Inpsyde\MultilingualPress\Framework\WordpressContext;

use function Inpsyde\MultilingualPress\preserveUrlRequestParams;

class Model
{
    public const FILTER_SHOULD_PRESERVE_LANGUAGE_SWITCHER_ITEM_URL_PARAMS = 'multilingualpress.languageSwitcher.should_preserve_url_params';

    /**
     * @var Translations
     */
    private $translations;

    /**
     * @var ItemFactory
     */
    private $itemFactory;

    /**
     * @var SiteSettingsRepository
     */
    protected $siteSettingsRepository;

    /**
     * Whether the ExternalSites module is active.
     *
     * @var bool
     */
    protected $isExternalSitesModuleActive;

    /**
     * @param Translations $translations
     * @param ItemFactory $itemFactory
     */
    public function __construct(
        Translations $translations,
        ItemFactory $itemFactory,
        SiteSettingsRepository $siteSettingsRepository,
        bool $isExternalSitesModuleActive
    ) {

        $this->translations = $translations;
        $this->itemFactory = $itemFactory;
        $this->siteSettingsRepository = $siteSettingsRepository;
        $this->isExternalSitesModuleActive = $isExternalSitesModuleActive;
    }

    /**
     * @param array $args
     * @param array $instance
     * @return array
     */
    public function data(array $args, array $instance): array
    {
        $translations = $this->translations();
        if (!$translations) {
            return [];
        }

        $model['before_title'] = $args['before_title'] ?? '';
        $model['title'] = $instance['title'] ?? '';
        $model['after_title'] = $args['after_title'] ?? '';
        // phpcs:ignore Inpsyde.CodeQuality.LineLength.TooLong
        $model['show_links_for_translated_content_only'] = $instance['show_links_for_translated_content_only'] ?? 0;
        $model['show_current_site'] = $instance['show_current_site'] ?? 0;
        $model['show_flags'] = $instance['show_flags'] ?? 0;
        $model['language_name'] = $instance['language_name'] ?? 'isoName';
        $model['items'] = [];

        if ($this->isExternalSitesModuleActive) {
            $model['show_external_sites'] = $instance['show_external_sites'] ?? 0;
        }

        foreach ($translations as $translation) {
            if ($translation->remoteSiteId() === get_current_blog_id() && $model['show_current_site'] !== 1) {
                continue;
            }

            /**
             * Filters if the URL params should be used for remote url.
             *
             * @param bool $shouldPreserveParams true if the params should be preserved, otherwise false.
             * @param Item $item
             */
            $shouldPreserveParams = apply_filters(self::FILTER_SHOULD_PRESERVE_LANGUAGE_SWITCHER_ITEM_URL_PARAMS, true, $translation);
            $remoteUrl = $translation->remoteUrl();
            $remoteUrlToUse = $shouldPreserveParams ? preserveUrlRequestParams($remoteUrl) : $remoteUrl;
            $url = $remoteUrl ? $remoteUrlToUse : get_home_url($translation->remoteSiteId(), '/');

            if ($model['show_links_for_translated_content_only'] === 1) {
                $url = $remoteUrlToUse;
            }
            if (!$url) {
                continue;
            }

            $language = $translation->language();

            $model['items'][] = $this->itemFactory->create(
                $language->{$model['language_name']}(),
                $language->bcp47tag(),
                $language->isoCode(),
                $this->languageFlag($model, $language->isoCode()),
                $url,
                $translation->remoteSiteId(),
                $this->hreflangDisplayCode($translation->remoteSiteId())
            );
        }

        return $model;
    }

    /**
     * @return Translation[]
     */
    protected function translations(): array
    {
        $args = TranslationSearchArgs::forContext(new WordpressContext())
            ->forSiteId(get_current_blog_id())
            ->includeBase();

        $translations = $this->translations->searchTranslations($args);

        return $translations;
    }

    /**
     * Returns flag image url from multilingualpress-site-flags plugin
     *
     * This is neeeded for old site-flags plugin to work.
     *
     * @param array $model
     * @param string $isoCode
     * @return string
     */
    protected function languageFlag(array $model, string $isoCode): string
    {
        if (interface_exists(Flag::class) && $model['show_flags'] === 1) {
            return plugins_url('multilingualpress-site-flags/', dirname(__DIR__, 3))
                . "resources/images/flags/{$isoCode}.gif";
        }

        return '';
    }

    public function hreflangDisplayCode($siteId): string
    {
        $hreflangDisplayType = $this->siteSettingsRepository->hreflangSettingForSite(
            $siteId,
            SiteSettingsRepository::NAME_HREFLANG_DISPLAY_TYPE
        );
        $hreflangDisplayTypeIsCountry = $hreflangDisplayType === 'country';

        $translations = $this->translations();
        $language = $translations[$siteId]->language();
        return $hreflangDisplayTypeIsCountry ? $language->isoCode() : $language->bcp47tag();
    }
}
