<?php

/**
 * The file that defines typography methods
 *
 * A class definition that includes attributes and functions used across both the
 * public-facing side of the site and the admin area.
 *
 * @link       https://flothemes.com/
 * @since      1.0.0
 *
 * @package    Flo_Flex_Builder
 * @subpackage Flo_Flex_Builder/includes
 */

/**
 * The core plugin class.
 *
 * This is used to define internationalization, admin-specific hooks, and
 * public-facing site hooks.
 *
 * Also maintains the unique identifier of this plugin as well as the current
 * version of the plugin.
 *
 * @since      1.0.0
 * @package    Flo_Flex_Builder
 * @subpackage Flo_Flex_Builder/includes
 * @author     Flothemes <alexb@flothemes.com>
 */
class Flo_Flex_Builder_Typography {
    /**
     * The unique identifier of this plugin.
     *
     * @since    1.0.0
     * @access   protected
     * @var      string    $plugin_name    The string used to uniquely identify this plugin.
     */
    protected $plugin_name;

    /**
     * The current version of the plugin.
     *
     * @since    1.0.0
     * @access   protected
     * @var      string    $version    The current version of the plugin.
     */
    protected $version;

    /**
     * Load class Flo_Flex_Builder_Typography
     *
     */
    public function __construct() {
        if (defined('Flo_Flex_Builder_Version')) {
            $this->version = Flo_Flex_Builder_Version;
        } else {
            $this->version = '0.1';
        }
        $this->plugin_name = 'flo-flex-stylekits';
    }

    /**
     * Generate css file with all items
     * @param $stylekit_id
     *
     */
    public static function generateCSSFile($stylekit_id) {
        //vars
        $all_stylekits = get_option('flex_all_stylekits_obj');
        $stylekits_obj = $all_stylekits ? $all_stylekits : [];
        $uploads_dir = wp_get_upload_dir();
        $uploads_dir_path = isset($uploads_dir['basedir']) ? $uploads_dir['basedir'] : false;

        if (!$uploads_dir_path) {
            return false;
        }

        $flex_user_data = get_option('flex_user_data');
        $custom_user_fonts = isset($flex_user_data['customUserFonts']) ? $flex_user_data['customUserFonts'] : [];
        $custom_user_groups = isset($flex_user_data['customFontGroups']) ? $flex_user_data['customFontGroups'] : [];
        $userdata_custom_fonts = is_array($custom_user_fonts) ? $custom_user_fonts : [];
        $general_custom_fonts = array_key_exists($stylekit_id, $all_stylekits) ? $all_stylekits[$stylekit_id]['generalInfo']['customFonts'] : [];

        $typekit_fonts = get_option('flex_typekit_manifest');
        if (!$typekit_fonts) $typekit_fonts = [];

        //get all css styles
        $fontStyles = [];
        $all_custom_fonts = [];
        if (array_key_exists($stylekit_id, $all_stylekits) && is_array($all_stylekits[$stylekit_id]['fonts']) && is_array($general_custom_fonts)) {
            $fontStyles = array_merge($all_stylekits[$stylekit_id]['fonts'], $custom_user_groups);
            $all_custom_fonts = array_merge($general_custom_fonts, $userdata_custom_fonts);
        }
        $font_faces = self::generateFontFaces($fontStyles, $all_custom_fonts, $typekit_fonts);
        $font_styles = self::generateFontStyles($stylekit_id, $stylekits_obj, $flex_user_data);
        $color_styles = self::generateColorStyles($stylekit_id, $stylekits_obj);
        $global_css = self::generateGlobalStyles();
        $final_style = $color_styles . $font_faces . $font_styles . $global_css;

        if (!file_exists("{$uploads_dir_path}/flex/stylekits")) {
            //create folder /flex/stylekits
            mkdir("{$uploads_dir_path}/flex/stylekits", 0777, true);
        }
        if (array_key_exists($stylekit_id, $stylekits_obj)) {
            //update css file
            file_put_contents("{$uploads_dir_path}/flex/stylekits/{$stylekit_id}.css", $final_style);
        }
    }

    /**
     * Generate css font faces based on stylekit id
     *
     * @param $stylekit_id
     * @param $all_custom_fonts
     * @return string
     */
    public static function generateFontFaces($fontStyles, $all_custom_fonts, $typekit_fonts = []) {
        //vars
        $font_faces = "";
        $generatedFonts = [];
        $typekit_fonts_obj = [];
        foreach ($typekit_fonts as $typekit_font) {
            $typekit_fonts_obj[$typekit_font['family']] = $typekit_font;
        }

        foreach ($fontStyles as $fontStyle) {
            $fontFamily = $fontStyle['fontFamily'];
            // generate id to get entry from $all_custom_fonts obj
            $fontId = strtolower(str_replace(' ', '_', $fontFamily));
            if (!isset($generatedFonts[$fontId]) && isset($all_custom_fonts[$fontId])) {
                $customFont = $all_custom_fonts[$fontId];
                foreach ($customFont['files'] as $customFontFile) {
                    //vars
                    $font_family = $customFontFile['name'];
                    $src = $customFontFile['url'];
                    $format = $customFontFile['format'];
                    $src = str_replace("http:", "", $src);
                    $src = str_replace("https:", "", $src);

                    $font_faces .= "
                        @font-face {
                            font-family: {$font_family}; 
                            src: url('{$src}');
                            font-display: swap;
                        }
                    ";
                }
                // add flag to ensure same font face isn't generated multiple times
                $generatedFonts[$fontId] = true;
            } else if (!isset($generatedFonts[$fontId]) && isset($typekit_fonts_obj[$fontId])) {
                if (isset($typekit_fonts_obj[$fontId]['css'])) {
                    $font_faces .= $typekit_fonts_obj[$fontId]['css'];
                }
            }
        }
        return self::minify_css($font_faces);
    }

    /**
     * Generate css font faces based on stylekit id
     *
     * @param $stylekit_id
     * @return string
     */
    public static function getGfontsUrl($stylekit_id) {
        //vars
        $all_stylekits = get_option('flex_all_stylekits_obj');
        $stylekits_obj = $all_stylekits ? $all_stylekits : [];
        $gfontsUrl = isset($stylekits_obj[$stylekit_id]['generalInfo']['gFontsUrl']) ? $stylekits_obj[$stylekit_id]['generalInfo']['gFontsUrl'] : false;

        return $gfontsUrl;
    }

    /**
     * Generate css font faces based on stylekit id
     *
     * @param $stylekit_id
     * @return string
     */
    public static function getCustomGfontsUrl() {
        //vars
        $flex_user_data = get_option('flex_user_data');
        $gfontsUrl = isset($flex_user_data['gFontsUrl']) ? $flex_user_data['gFontsUrl'] : false;

        return $gfontsUrl;
    }

    public static function getMobileVal($fontObj, $key) {
        if (isset($fontObj['mobile'][$key]) && $fontObj['mobile'][$key] !== null) {
            $val = $fontObj['mobile'][$key];
        } else {
            $val = $fontObj[$key];
        }
        return $val;
    }

    public static function getTabletVal($fontObj, $key) {
        if (isset($fontObj['tablet'][$key]) && $fontObj['tablet'][$key] !== null) {
            $val = $fontObj['tablet'][$key];
        } else {
            $val = $fontObj[$key];
        }
        return $val;
    }

    /**
     * Generate font styles based on stylekit id
     *
     * @param $stylekit_id
     * @param $stylekits_obj
     * @return string
     */
    public static function generateFontStyles($stylekit_id, $stylekits_obj, $flex_user_data) {
        //vars
        $css = "";
        $mobile_css = "";
        $tablet_css = "";

        $flex_admin_mobile_css = "";
        $flex_admin_tablet_css = "";
        $mobile_canvas_selector = ".flex-mc";
        $tablet_canvas_selector = ".flex-tc";
        $fontGroups = isset($stylekits_obj[$stylekit_id]['fonts']) ? $stylekits_obj[$stylekit_id]['fonts'] : [];

        if (isset($flex_user_data['customFontGroups'])) {
            $fontGroups = array_merge($fontGroups, $flex_user_data['customFontGroups']);
        }
        if ($fontGroups) {
            $mobile_css = "@media (max-width: 767px) {";

            foreach ($fontGroups as $fontCSS) {
                //vars
                $fontKey = $fontCSS['id'];
                $lineHeight = $fontCSS['lineHeight'] . 'em';
                $fontSize = $fontCSS['fontSize'] / 16 . 'rem';
                $letterSpacing = $fontCSS['letterSpacing'] . 'em';
                $fontFamily = $fontCSS['fontFamily'];
                $fontWeight = $fontCSS['fontWeight'];
                $fontStyle = $fontCSS['fontStyle'];
                $textDecoration = $fontCSS['textDecoration'];
                $textTransform = $fontCSS['textTransform'];


                $font_class = "body [data-font='{$fontKey}']";
                $flex_mobile_admin_selector = "body {$mobile_canvas_selector} [data-font='{$fontKey}']";

                if ($fontKey == 'third_level/primary_cta') {
                    $font_class .= ',body .flo-generic-button, body input[type="submit"]';
                }

                $style = "{
                    font-family: {$fontFamily};
                    font-size: {$fontSize};
                    font-weight: {$fontWeight};
                    font-style: {$fontStyle};
                    line-height: {$lineHeight};
                    letter-spacing: {$letterSpacing};
                    text-decoration: {$textDecoration};
                    text-transform: {$textTransform};
                }";

                $css .=  $font_class . $style;

                if (isset($fontCSS['mobile'])) {
                    //vars
                    $mobile_fontSize = self::getMobileVal($fontCSS, 'fontSize') / 16 . 'rem';
                    $mobile_lineHeight = self::getMobileVal($fontCSS, 'lineHeight') . 'em';
                    $mobile_letterSpacing = self::getMobileVal($fontCSS, 'letterSpacing') . 'em';

                    $mobile_style = "{
                        font-size: {$mobile_fontSize};
                        line-height: {$mobile_lineHeight};
                        letter-spacing: {$mobile_letterSpacing};
                    }";

                    $mobile_css .= $font_class . $mobile_style;
                    $flex_admin_mobile_css .= $flex_mobile_admin_selector . $mobile_style;
                }
            }
            $mobile_css .= "}";

            $tablet_css = "@media (min-width: 768px) and (max-width:1024px) {";

            foreach ($fontGroups as $fontCSS) {
                //vars
                $fontKey = $fontCSS['id'];
                $lineHeight = $fontCSS['lineHeight'] . 'em';
                $fontSize = $fontCSS['fontSize'] / 16 . 'rem';
                $letterSpacing = $fontCSS['letterSpacing'] . 'em';
                $fontFamily = $fontCSS['fontFamily'];
                $fontWeight = $fontCSS['fontWeight'];
                $fontStyle = $fontCSS['fontStyle'];
                $textDecoration = $fontCSS['textDecoration'];
                $textTransform = $fontCSS['textTransform'];


                $font_class = "body [data-font='{$fontKey}']";
                $flex_tablet_admin_selector = "body {$tablet_canvas_selector} [data-font='{$fontKey}']";

                if ($fontKey == 'third_level/primary_cta') {
                    $font_class .= ',body .flo-generic-button, body input[type="submit"]';
                }

                $style = "{
                        font-family: {$fontFamily};
                        font-size: {$fontSize};
                        font-weight: {$fontWeight};
                        font-style: {$fontStyle};
                        line-height: {$lineHeight};
                        letter-spacing: {$letterSpacing};
                        text-decoration: {$textDecoration};
                        text-transform: {$textTransform};
                    }";

                $css .=  $font_class . $style;

                if (isset($fontCSS['tablet'])) {
                    //vars
                    $tablet_fontSize = self::getTabletVal($fontCSS, 'fontSize') / 16 . 'rem';
                    $tablet_lineHeight = self::getTabletVal($fontCSS, 'lineHeight') . 'em';
                    $tablet_letterSpacing = self::getTabletVal($fontCSS, 'letterSpacing') . 'em';

                    $tablet_style = "{
                            font-size: {$tablet_fontSize};
                            line-height: {$tablet_lineHeight};
                            letter-spacing: {$tablet_letterSpacing};
                        }";

                    $tablet_css .= $font_class . $tablet_style;
                    $flex_admin_tablet_css .= $flex_tablet_admin_selector . $tablet_style;
                }
            }
            $tablet_css .= "}";
        }

        return self::minify_css($css . $mobile_css . $flex_admin_mobile_css . $tablet_css . $flex_admin_tablet_css);
    }

    /**
     * Generate color styles based on stylekit id
     *
     * @param $stylekit_id
     * @param $stylekits_obj
     * @return string
     */
    public static function generateColorStyles($stylekit_id, $stylekits_obj) {
        //vars
        $colors_css = ":root {";

        if (isset($stylekits_obj[$stylekit_id]['colors'])) {
            foreach ($stylekits_obj[$stylekit_id]['colors'] as $color) {
                //vars
                $color_id = self::formatColorName($color['id']);
                $color_name = $color['id'];
                $color_value = $color['value'];

                $colors_css .= "
                    --{$color_id}: $color_value;
                ";
            }
        }
        $colors_css .= "}";

        return self::minify_css($colors_css);
    }

    /**
     * Generate color styles based on stylekit id
     *
     * @return string
     */
    public static function generateGlobalStyles() {
        $generic_css = '
            body:not(.wp-admin) {
              background-color: var(--scheme_1--background--default);
              color: var(--scheme_1--text--default);
            }
        
            .flo-post {
              color: var(--scheme_1--text--default);
            }
        
            .flo-generic-button--scheme-1 {
              color: var(--scheme_1--button--text--default);
              background-color: var(--scheme_1--button--background--default);
            }
            .flo-generic-button--scheme-1:hover {
              color: var(--scheme_1--button--text--hover);
              background-color: var(--scheme_1--button--background--hover);
            }
        
            .flo-generic-button--scheme-2 {
              color: var(--scheme_2--button--text--default);
              background-color: var(--scheme_2--button--background--default);
            }
            .flo-generic-button--scheme-2:hover {
              color: var(--scheme_2--button--text--hover);
              background-color: var(--scheme_2--button--background--hover);
            }';

        return self::minify_css($generic_css);
    }

    /**
     * Remove tabs from string
     *
     * @param $string
     * @return string
     */
    public static function minify_css($string) {
        // comments
        $string = preg_replace('!/\*.*?\*/!s', '', $string);
        $string = preg_replace('/\n\s*\n/', "\n", $string);

        // space
        $string = preg_replace('/[\n\r \t]/', ' ', $string);
        $string = preg_replace('/ +/', ' ', $string);
        $string = preg_replace('/ ?([,:;{}]) ?/', '$1', $string);

        // trailing;
        $string = preg_replace('/;}/', '}', $string);
        return $string;
    }


    /**
     * Get color name and replace with --
     *
     * @param $colorName
     * @return string
     */
    public static function formatColorName($colorName) {
        return str_replace('/', '--', $colorName);
    }
}
