<?php

/**
 * Generates data for the FlexBlock builder interface
 *
 * Main purpose of this class is to localize variables via wp_localize_script
 * localized variables will include:
 * - links to stylekit css files and gfonts
 * - font styles keys and labels: title_1/large => Title 1/Large
 * - color keys and labels: scheme_1--background--default => Scheme 1/Background/Default
 */
class Flex_Builder_Data {

  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-builder';

    add_action('admin_enqueue_scripts', [$this, 'localizeData']);
  }

  /**
   * return fonts fonts data if used on flothemes.com
   */
  public function flothemesFonts() {
    $flothemesFontList = flex_get_field('flex_font_list', 'options');
    if (is_array($flothemesFontList) && sizeof($flothemesFontList)) {
      $fontNames = [];
      $fontFaces = "";
      foreach ($flothemesFontList as $font) {
        if ((isset($font['font_name']) && strlen($font['font_name'])) && (isset($font['font_url']) && strlen($font['font_url']))) {
          $fontNames[$font['font_name']] = $font['font_name'];
          $fontFaces .= ' @font-face {font-family: "' . $font['font_name'] . '"; src: url(' . $font['font_url'] . ')}';
        }
      }

      $flothemes_font_map = [
        'fontNames' => $fontNames,
        'fontFaces' => $fontFaces
      ];

      return $flothemes_font_map;
    }

    return false;
  }

  /**
   * pull ACF typography data and reformat it to a structure friendly for flex
   * @return array
   * [
   *  'fontNames' => $font_names,
   *  'fontFaces' => $font_faces,
   *  'fontStyles' => $font_styles,
   *  'themeGFontsURL' => $g_url
   * ]
   */
  public function getAcfTypography() {
    $font_faces = '';
    $font_names = [];
    $google_font_face = [];
    $theme_typography_option_name = 'flo-typography';
    $theme_typography_option_name = apply_filters('flo_theme_typography_option_name', $theme_typography_option_name);
    $flo_typography = flex_get_field($theme_typography_option_name, 'options');
    if (isset($flo_typography['font_styles'])) {
      if (is_string($flo_typography['font_styles'])) {
        $font_styles_data = json_decode($flo_typography['font_styles']);
      } else {
        $font_styles_data = (array) $flo_typography['font_styles'];
      }

      if (is_object($font_styles_data)) {

        $theme_defaults = [];
        $user_specified = [];
        $font_styles = [];

        if (isset($font_styles_data->theme_defaults)) {
          $theme_defaults = $font_styles_data->theme_defaults;
        }
        if (isset($font_styles_data->user_specified)) {
          $user_specified = $font_styles_data->user_specified;
        }

        // merge the 2 objects to have only 1 iteration for both
        $typography_styles = (object) array_merge((array) $theme_defaults, (array) $user_specified);
        // iterate and construct font data

        foreach ($typography_styles as $fontName => $value) {
          $font_face = get_font_face($value);
          $font_style_css = get_font_styles($value);

          $font_styles[$fontName] = [
            'name' => $value->font_style_name,
            'style' => $font_style_css['default'],
            'mobile_style' => $font_style_css['mobile']
          ];

          if (isset($value->font_family) && !in_array($value->font_family, $font_names)) {

            if (isset($font_face['custom_font_face'])) {
              $font_faces .= $font_face['custom_font_face'];
              $font_names[$value->font_family] = $value->font_family;
            } else if (isset($font_face['google_font_face']) && !in_array($font_face['google_font_face'], $google_font_face)) {
              $google_font_face[] = $font_face['google_font_face'];
              $font_names[$font_face['google_font_face']] = $font_face['google_font_face'];
            }
          }
        }
      }
    }

    if (sizeof($google_font_face)) {

      $site_url = get_site_url();
      $isHttps = strpos($site_url, 'https') !== false;
      $g_url = [];
      if (!$isHttps) {
        foreach ($google_font_face as $i => $googleFont) {
          $family_name = trim(str_replace(' ', '+', $googleFont));
          $query_args = ['family' => $family_name];
          $g_url[] = add_query_arg($query_args, "//fonts.googleapis.com/css");
        }
      } else {
        $family_name = implode('|', $google_font_face);
        $family_name = trim(str_replace(' ', '+', $family_name));
        $query_args = ['family' => $family_name];
        $g_url[] = add_query_arg($query_args, "//fonts.googleapis.com/css");
      }
    }

    // custom_fonts
    if (isset($flo_typography['custom_fonts']) && strlen($flo_typography['custom_fonts'])) {
      $custom_fonts_data = json_decode($flo_typography['custom_fonts']);
      $custom_fonts_generated = acf_field_flo_typography::process_custom_fonts_list($custom_fonts_data);
      if (gettype($custom_fonts_generated) === 'array' && sizeof($custom_fonts_generated)) {
        foreach ($custom_fonts_generated as $font_data) {
          $custom_font_name = $font_data['font_family'];
          $font_names[$custom_font_name] = $custom_font_name;
          $custom_font_face = acf_field_flo_quick_typography::get_custom_font_face($font_data);
          $font_faces .= $custom_font_face;
        }
      }
    }

    $font_map = [
      'fontNames' => $font_names,
      'fontFaces' => $font_faces
    ];

    if (isset($font_styles)) {
      $font_map['fontStyles'] = $font_styles;
    }
    if (isset($g_url)) {
      $font_map['themeGFontsURL'] = $g_url;
    }

    return $font_map;
  }

  /**
   * looks for local flex blocks files in the theme (to be found in theme/theme-files/flex-blocks)
   */
  public function loadLocalBlocks() {
    if (file_exists(get_template_directory() . "/theme-files/flex-base/flex-blocks/flex-blocks-config.json")) {
      $blocks_config_file = get_template_directory() . '/theme-files/flex-base/flex-blocks/flex-blocks-config.json';
    } else {
      $blocks_config_file = get_template_directory() . '/theme-files/flex-blocks/flex-blocks-config.json';
    }

    if (file_exists($blocks_config_file)) {
      $file_content = file_get_contents($blocks_config_file);
      $blocks = json_decode($file_content, true);
      if (file_exists(get_template_directory() . "/theme-files/flex-base/flex-blocks/blocks-list/")) {
        $blocks_config_file = get_template_directory_uri() . '/theme-files/flex-base/flex-blocks/blocks-list/';
      } else {
        $blocks_config_file = get_template_directory_uri() . '/theme-files/flex-blocks/blocks-list/';
      }
      $blocks_data = ["blocks" => $blocks, "folder_path" => $blocks_config_file];

      return $blocks_data;
    } else {
      return false;
    }
  }

  /**
   * pull colors data from acf and format to a simpler structure
   */
  public static function getAcfColorsData() {
    $acf_scheme_1 = flex_get_field('scheme_1', 'options');
    $acf_scheme_2 = flex_get_field('scheme_2', 'options');
    $acf_colors = !empty($acf_scheme_1) ? array_merge($acf_scheme_1, $acf_scheme_2) : [];
    $flex_stylekit_color_list = [];
    $flex_stylekit_color_labels = [];

    if (!empty($acf_colors)) {
      foreach ($acf_colors as $color_name => $color_value) {
        $color_obj = get_field_object($color_name, 'options');

        if ($color_obj !== false) {
          $color_label = $color_obj['label'];
          $flex_stylekit_color_labels[$color_name] = $color_label;
          if ($color_obj['value']) {
            $flex_stylekit_color_list[$color_name] = $color_obj['value'];
          } else {
            $flex_stylekit_color_list[$color_name] = $color_obj['default_value'];
          }
        }
      }
    } elseif (function_exists("flo_get_current_style_kit")) {
      $current_stylekit = flo_get_current_style_kit();
      if (file_exists(get_template_directory() . "/theme-files/flo_stylekits_config/" . $current_stylekit . "/colors_settings.php")) {
        include(get_template_directory() . "/theme-files/flo_stylekits_config/" . $current_stylekit . "/colors_settings.php");

        if (isset($color_settings) && is_array($color_settings)) {
          foreach ($color_settings as $color_name => $color_value) {
            $color_obj = get_field_object($color_name, 'options');
            if (!is_array($color_obj)) continue;
            $color_label = $color_obj['label'];
            $flex_stylekit_color_labels[$color_name] = $color_label;

            if ($color_obj['value']) {
              $flex_stylekit_color_list[$color_name] = $color_obj['value'];
            } else {
              $flex_stylekit_color_list[$color_name] = $color_obj['default_value'];
            }
          }
        }
      }
    }

    return [
      'flex_stylekit_color_list' => $flex_stylekit_color_list,
      'flex_stylekit_color_labels' => $flex_stylekit_color_labels
    ];
  }

  /**
   * return fonts, colors data from stylekit
   * is called if FLEX_STYLEKIT constant is defined
   * @param null $post_id
   * @return array|bool
   */
  public static function getFlexStylekitStyles($post_id = null) {

    $stylekits_typography = new Flo_Flex_Builder_Typography_Post_Check();
    $fileLinks = $stylekits_typography->getStylekitStyleLinks($post_id);

    if ($fileLinks) {
      $stylekitId = $stylekits_typography->getPostStylekit($post_id);
      $allStylekits = get_option('flex_all_stylekits_obj');
      if (isset($allStylekits[$stylekitId])) {
        $stylekit = $allStylekits[$stylekitId];
        $customFontGroups = get_option('flex_user_data');
        // format colors to return font style keys and labels
        // also gather font names to be used in the "custom" tab of the flex typography editor
        if (isset($customFontGroups['customFontGroups'])) {
          $fontStylesData = array_merge($stylekit['fonts'], $customFontGroups['customFontGroups']);
        } else {
          $fontStylesData = $stylekit['fonts'];
        }
        $fontNames = [];
        $fontStyles = [];
        foreach ($fontStylesData as $key => $fontStyle) {
          $label = $fontStyle['label'];
          $source = false;
          $author = false;
          if (isset($fontStyle['source'])) {
            $source = $fontStyle['source'];
          }
          if (isset($fontStyle['author'])) {
            $author = $fontStyle['author'];
          }
          $fontFamily = $fontStyle['fontFamily'];
          $fontStyles[$key] = ['name' => $label, 'source' => $source, 'author' => $author];
          $fontNames[$fontFamily] = $fontFamily;
        }

        // get stylekit color values and labels
        // these are separated in separate arrays for easier data handling
        $colors = $stylekit['colors'];
        $color_values = [];
        $color_labels = [];
        foreach ($colors as $id => $color) {
          $color_values[$id] = $color['value'];
          $color_labels[$id] = $color['name'];
        }

        // combine all data in a single array
        $stylekitData = [
          'fontData' => [
            'fontNames' => $fontNames,
            'fontStyles' => $fontStyles,
            'links' => $fileLinks,
          ],
          'colors' => [
            'values' => $color_values,
            'labels' => $color_labels
          ]
        ];

        return $stylekitData;
      }
    }

    return false;
  }

  /**
   * generates variables that will be localized for flex to use in js
   * if flex is used on flothemes.com, only flothemes.com specific fonts will be returned
   * if flex is used on a classic theme or a flextheme without installed stylekits data, will return fonts, colors from the theme
   * if is a flex theme with stylekits, will return stylekit data for the current accessed page
   */
  public function getVariables() {
    $variables = [];

    $isFlothemes = Flo_Flex_Builder::isFlothemes();

    if ($isFlothemes) {
      $variables['flothemes_font_map'] = $this->flothemesFonts();
    } else {
      if (!defined('FLEX_STYLEKITS')) {
        $variables['flothemes_font_map'] = $this->getAcfTypography();
        $oldColorsData = self::getAcfColorsData();
        if ($oldColorsData) {
          $variables['flex_stylekit_color_list'] = $oldColorsData['flex_stylekit_color_list'];
          $variables['flex_stylekit_color_labels'] = $oldColorsData['flex_stylekit_color_labels'];
        }
      } else {
        $stylekitData = self::getFlexStylekitStyles();
        if ($stylekitData) {
          $colorsData = $stylekitData['colors'];

          $variables['flothemes_font_map'] = $stylekitData['fontData'];
          $variables['flex_stylekit_color_list'] = $colorsData['values'];
          $variables['flex_stylekit_color_labels'] = $colorsData['labels'];
        }
      }

      // local blocks
      $blocks = $this->loadLocalBlocks();
      if ($blocks && is_array($blocks) && sizeof($blocks)) {
        $variables['flex_predefined_blocks'] = $blocks;

        $userInfo = get_option('userInfo');
      }
    }

    // Global Elements
    $variables['flex_global_elements'] = Flo_Flex_Builder_Admin::get_global_elements();

    $upload_dir = wp_upload_dir();

    $variables['flex_data_window'] = array(
      "flex_global_elements" => Flo_Flex_Builder_Admin::get_global_elements(),
      "flex_global_block_options" => get_option('flex_global_block_options', array()),
      "flex_global_post_type" => get_post_type(),
      "flex_global_primary_menu_id" => (string)flex_get_default_menu_id(),
      "flex_dev_mode" => Flex_Dev_Mode,
      "flex_gutenberg_mode" => FLEX_GUTENBERG,
      "flex_dev_features_enabled" => FLEX_DEV_FEATURES_ENABLED,
      "admin_url" => admin_url(),
      'gutenberg_iframe' => defined('Flex_Dev_Mode') && true === Flex_Dev_Mode ? 'http://localhost:8000' : plugins_url() . '/flo-flex-builder/admin/partials/acf-flo-flex-builder/app/index.html?ver=' . $this->version,
      'flex_templates_config' => json_encode(isset($userInfo['templatesConfig']) ? $userInfo['templatesConfig'] : false),
      'flex_templates_permission' => json_encode(isset($userInfo['permissionForMono']) ? $userInfo['permissionForMono'] : false),
      'flex_show_case' => defined('FLEX_SHOW_CASE') && FLEX_SHOW_CASE,
      'is_flex_theme' => defined('FLEX_THEME') && FLEX_THEME,
      'version' => Flo_Flex_Builder_Version,
      'uploads_dir' => $upload_dir['baseurl']
    );

    return $variables;
  }

  /**
   * main class function
   * gets all necessary variables depending on the detected use-case and localizes them
   */
  public function localizeData() {
    $variables = $this->getVariables();

    if (sizeof($variables)) {
      foreach ($variables as $key => $value) {
        if (is_array($value)) {
          wp_localize_script($this->plugin_name, $key, $value);
        } else {
          // Localization fails if value is not array!
        }
      }
    }
  }
}
