<?php
    /**
     * Manage all fonts used in the theme
     * Data is retrieved from customizer
     * 
     * @package Blog Bee
     * @since 1.0.0
     */

    namespace BBE;
    use BBE\Customizer\Theme_Defaults as Theme_Defaults;
    use BBE\Customizer\Section\Section as Section;
    use Utility;

    /**
     * Web font loader
     */
    require_once get_template_directory() . '/inc/wptt-webfont-loader.php';

    use wptt_get_webfont_url;

    if( ! class_exists( __NAMESPACE__ . '\\Font_Manager' ) ) {
        /**
         *  Font manager class
         */
        class Font_Manager {

            /**
             * Instance of class
             * 
             * @since 1.0.0
             */
            private static $instance = null;

            /**
             * Get instance
             * 
             * @since 1.0.0
             */
            public static function get_instance() {
                if( self::$instance === null ) self::$instance = new self();

                return self::$instance;
            }

            /**
             * Google link
             * 
             * @since 1.0.0
             */
            private static $link = 'https://fonts.googleapis.com/css2';

            /**
             * Fonts
             * 
             * @since 1.0.0
             */
            private static $fonts = [];

            /**
             * Add fonts
             * 
             * @since 1.0.0
             * @param array{
            *     Roboto: array{
            *         normal: array<string>,
            *         italic: array<string>
            *     }
            * } $new_font
             */
            public static function add_font( $new_font ) {
                self::$fonts = array_merge( self::$fonts, $new_font );
            }

            /**
             * Get all used google fonts
             * 
             * @since 1.0.0
             */
            public function set_fonts() {
                $controls_by_type = Utility::get_controls_by_type();
                $typographies = $controls_by_type[ 'typography' ];
                foreach( $typographies as $typography ) {
                    $value = Theme_Defaults::get_theme_option( $typography );
                    $font_family_value = $value[ 'font_family' ][ 'value' ];
                    $font_weight = $value[ 'font_weight' ];
                    $is_italic = $this->is_italic( $font_weight );
                    $weight_key = $is_italic ? 'italic' : 'normal';

                    if( ! isset( self::$fonts[ $font_family_value ] ) ) {
                        self::$fonts[ $font_family_value ] = [
                            'normal'  =>  [],
                            'italic'  =>  []
                        ];
                        self::$fonts[ $font_family_value ][ $weight_key ][] = $font_weight;
                    } else {
                        if( ! in_array( $font_weight, self::$fonts[ $font_family_value ][ $weight_key ] ) ) {
                            self::$fonts[ $font_family_value ][ $weight_key ][] = $font_weight;
                        }
                    }
                }
            }

            /**
             * Check if font is italic
             * 
             * @since 1.0.0
             * @param   string  $font_weight    The font weight to check
             */
            private function is_italic( $font_weight ): bool {
                return strpos( $font_weight, 'italic' ) !== false;
            }

            /**
             * Convert to link
             * 
             * @since 1.0.0
             */
            public static function get_font_links() {
                $used_fonts = self::get_used_google_fonts();
                $link_args = [];
                foreach( $used_fonts as $family => $weights ) {
                    $link_args[ $family ] = '';
                    $normal_weights = $weights[ 'normal' ];
                    $italic_weights = $weights[ 'italic' ];
                    $use_both_variants = ! empty( $italic_weights );
                    $variants = $use_both_variants ? 'ital,wght@' : 'wght@';
                    $link = 'family=' . $family . ':' . $variants;
                    if( $use_both_variants ) {
                        $weights = '';
                        $weights .= implode( ';', array_map( fn( $w ) => '0,'. self::get_clean_weight( $w ), $normal_weights ) ) . ';';
                        $weights .= implode( ';', array_map( fn( $w ) => '1,'. self::get_clean_weight( $w ), $italic_weights ) );
                        $link .= $weights;
                        $link_args[ $family ] = $link;
                    } else {
                        $link .= implode( ';', array_map( fn( $w ) => self::get_clean_weight( $w ), $normal_weights ) );
                        $link_args[ $family ] = $link;
                    }
                }
                return $link_args;
            }

            /**
             * Get fonts
             * 
             * @since 1.0.0
             */
            public static function get_used_google_fonts() {
                self::get_instance()->set_fonts();
                return self::$fonts;
            }

            /**
             * Get clean weight
             * 
             * @since 1.0.0
             * @param   string  $font_weight    The font weight to clean
             */
            private static function get_clean_weight( $font_weight ): string {
                if( in_array( $font_weight, [ 'regular', 'italic' ] ) ) $font_weight = '400';
                $clean_weight = preg_replace( '/(italic|regular)/i', '', $font_weight );
                $trimmed_weight = trim( $clean_weight );
                return $trimmed_weight;
            }

            /**
             * Get full google link
             * 
             * @since 1.0.0
             */
            public static function get_full_google_link() {
                $controls_by_type = Utility::get_controls_by_type();
                if( ! isset( $controls_by_type[ 'typography' ] ) ) return;
                self::$link .= '?' . implode( '&', self::get_font_links() ) . '&display=swap';
                return wptt_get_webfont_url( self::$link );
            }

            /**
             * Get local woff2 URLs to preload for specific fonts/weights
             *
             * @since 1.0.0
             */
            public static function get_preload_urls() {
                $preload_urls = [];
                $families_to_preload = self::get_used_google_fonts();
                
                foreach ( $families_to_preload as $family => $weights ) {
                    $normal_weights = $weights[ 'normal' ] ?? [];
                    $italic_weights = $weights[ 'italic' ] ?? [];

                    if ( empty( $normal_weights ) && empty( $italic_weights ) ) {
                        continue;
                    }

                    $use_both_variants = ! empty( $italic_weights );
                    $variants = $use_both_variants ? 'ital,wght@' : 'wght@';
                    $link = 'family=' . $family . ':' . $variants;

                    if ( $use_both_variants ) {
                        $weight_string = '';
                        $weight_string .= implode( ';', array_map( fn( $w ) => '0,' . self::get_clean_weight( $w ), $normal_weights ) );
                        $weight_string .= ! empty( $normal_weights ) ? ';' : '';
                        $weight_string .= implode( ';', array_map( fn( $w ) => '1,' . self::get_clean_weight( $w ), $italic_weights ) );
                        $link .= $weight_string;
                    } else {
                        $link .= implode( ';', array_map( fn( $w ) => self::get_clean_weight( $w ), $normal_weights ) );
                    }

                    $single_font_link = self::$link . '?' . $link . '&display=swap';

                    // Downloads css + font files locally, returns local stylesheet URL.
                    $local_css_url = wptt_get_webfont_url( $single_font_link, 'woff2' );

                    // Convert the local stylesheet URL to a filesystem path so we can read it.
                    $css_path = str_replace( content_url(), WP_CONTENT_DIR, $local_css_url );

                    if ( ! file_exists( $css_path ) ) {
                        continue;
                    }

                    $css_content = file_get_contents( $css_path );
                    preg_match_all( '/url\(([^)]+\.woff2)\)/', $css_content, $matches );

                    if ( ! empty( $matches[1] ) ) {
                        foreach ( $matches[1] as $url ) {
                            $preload_urls[] = trim( $url, "'\"" );
                        }
                    }
                }

                return array_unique( $preload_urls );
            }

        }
    }