<?php

namespace auctionforge\inc\helpers;

/**
 * Regional spelling dialect for the word "catalog" / "catalogue".
 *
 *   US dialect -> "Catalog"   (the plugin's authored strings, left unchanged)
 *   UK dialect -> "Catalogue"
 *
 * The front-end swap is performed with a `gettext` filter scoped to the
 * `auctionforge` text domain, so no template files need editing. Because the
 * filter only rewrites translated, user-facing strings it leaves every code
 * identifier, CSS class (e.g. `af-catalog-sidebar`, `catalog-section`),
 * JS variable and option key (e.g. `catalog_layout`, `bids_in_catalog`)
 * completely untouched.
 *
 * The dialect is chosen in: AuctionForge -> Settings -> Appearance.
 */
class Dialect
{
    const OPTION = 'spelling_dialect';
    const US = 'us';
    const UK = 'uk';

    /**
     * Default dialect for sites that have not chosen one. UK ("Catalogue").
     */
    const DEFAULT_DIALECT = self::UK;

    /** @var string|null Cached, normalised dialect for the current request. */
    private static $dialect = null;

    /**
     * Active dialect for this site: self::US or self::UK.
     * @return string
     */
    public static function get()
    {
        if (self::$dialect === null) {
            $value = SettingsHelper::getOption(self::OPTION, self::DEFAULT_DIALECT);
            self::$dialect = ($value === self::US) ? self::US : self::UK;
        }
        return self::$dialect;
    }

    /**
     * @return bool True when the active dialect is UK ("Catalogue").
     */
    public static function isUk()
    {
        return self::get() === self::UK;
    }

    /**
     * Return the catalog word in the active dialect, matching the casing and
     * pluralisation of $sample. Use this for any string that is NOT routed
     * through __() (the gettext filter handles everything that is).
     *
     * @param string $sample e.g. 'Catalog', 'catalog', 'CATALOG', 'Catalogs'
     * @return string
     */
    public static function word($sample = 'Catalog')
    {
        return self::isUk() ? self::toUk($sample) : $sample;
    }

    /**
     * `gettext` filter callback. Swaps US -> UK spelling in auctionforge
     * front-end strings.
     *
     * @param string $translation
     * @param string $text   (unused, kept for the filter signature)
     * @param string $domain
     * @return string
     */
    public static function filterGettext($translation, $text, $domain)
    {
        if ($domain !== 'auctionforge') {
            return $translation;
        }
        // Only the public-facing site, never the wp-admin settings UI. This
        // keeps admin field labels as authored and, importantly, keeps the
        // dialect dropdown's own "Catalog" / "Catalogue" option labels literal
        // so the choice stays self-explanatory. wp_doing_ajax() guards the
        // admin-ajax case (is_admin() is true there even for front-end AJAX).
        if (is_admin() && !wp_doing_ajax()) {
            return $translation;
        }
        return self::toUk($translation);
    }

    /**
     * `gettext_with_context` filter callback (4-arg signature).
     *
     * @param string $translation
     * @param string $text
     * @param string $context
     * @param string $domain
     * @return string
     */
    public static function filterGettextWithContext($translation, $text, $context, $domain)
    {
        return self::filterGettext($translation, $text, $domain);
    }

    /**
     * Replace whole-word "catalog"/"catalogs" with British "catalogue"/
     * "catalogues", preserving case (lower / Title / UPPER) and pluralisation.
     * Idempotent: input that already reads "catalogue" is returned unchanged,
     * and words such as "cataloged" / "subcatalog" are left alone.
     *
     * @param string $text
     * @return string
     */
    public static function toUk($text)
    {
        if ($text === '' || stripos($text, 'catalog') === false) {
            return $text;
        }
        return preg_replace_callback('/\bcatalog(ue)?(s)?\b/i', function ($m) {
            $matched = $m[0];
            $plural  = (substr(strtolower($matched), -1) === 's');
            $british = $plural ? 'catalogues' : 'catalogue';

            if ($matched === strtoupper($matched)) {
                return strtoupper($british);   // CATALOG(S) -> CATALOGUE(S)
            }
            if ($matched[0] === strtoupper($matched[0])) {
                return ucfirst($british);      // Catalog(S) -> Catalogue(s)
            }
            return $british;                   // catalog(s) -> catalogue(s)
        }, $text);
    }

    /**
     * Register the front-end gettext swap. No-op (zero added overhead) when the
     * active dialect is US, so US sites pay nothing.
     */
    public static function register()
    {
        if (!self::isUk()) {
            return;
        }
        add_filter('gettext', array(__CLASS__, 'filterGettext'), 10, 3);
        add_filter('gettext_with_context', array(__CLASS__, 'filterGettextWithContext'), 10, 4);
    }
}
