<?php

// Exit if accessed directly.
if (!defined('ABSPATH')) exit;

/**
 * Class Rdg_Blocks_Helpers
 *
 * This class contains repetitive functions that
 * are used globally within the plugin.
 *
 * @package		RDGBLOCKS
 * @subpackage	Classes/Rdg_Blocks_Helpers
 * @author		RDGCorp
 * @since		1.0.0
 */
class Rdg_Blocks_Helpers
{
    /**
     * The blocks cache directory
     *
     * @var		array
     * @since   1.0.13
     */

    private $cache_dir;

    /**
     * The blocks cache suffix
     *
     * @var		array
     * @since   1.0.13
     */

    private $cache_suffix;

    /**
     * Redis Service
     *
     * @var		class
     * @since   1.0.68
     */

     private $redis_cache;
     private $redis_cache_group;

    /**
     * Our Rdg_Blocks_Settings constructor 
     * to run the plugin logic.
     *
     * @since 1.0.0
     */

    function __construct() {
        $this->cache_dir = wp_upload_dir()['basedir'].'/'.RDGBLOCKS_NAME_SLUG.'/';
        $this->cache_suffix = '-cache.log';
        $this->redis_cache = $this->init_redis();
        $this->set_redis_group();
        
    }

    public function get_cache_dir() {
        return $this->cache_dir;
    }

    public function webpack($file, $buildDirectory = 'dist') {
        static $manifest;
        static $manifestPath;

        if (is_null($manifest) || $manifestPath !== $buildDirectory) {
            $manifest = json_decode(
                file_get_contents(RDGBLOCKS_PLUGIN_URL.$buildDirectory.'/manifest.json'),
                true
            );

            $manifestPath = $buildDirectory;
        }

        if (isset($manifest[$file])) {
            return RDGBLOCKS_PLUGIN_URL.trim($buildDirectory.'/'.$manifest[$file], '/');
        }

        throw new InvalidArgumentException("File {$file} not defined in asset manifest.");
    }

    public function get_blocks_spaces($fields) {
        $styles = [];

        if (!empty($fields['top'])) {
            $styles[] = $fields['top']['top_type'].'-top: '.$fields['top']['top_space'].'rem';
        }

        if (!empty($fields['right'])) {
            $styles[] = $fields['right']['right_type'].'-right: '.$fields['right']['right_space'].'rem';
        }

        if (!empty($fields['bottom'])) {
            $styles[] = $fields['bottom']['bottom_type'].'-bottom: '.$fields['bottom']['bottom_space'].'rem';
        }

        if (!empty($fields['left'])) {
            $styles[] = $fields['left']['left_type'].'-left: '.$fields['left']['left_space'].'rem';
        }

        if (count($styles) > 0) {
            return implode('; ', $styles).';';
        }

        return '';
    }

    public function get_title($fields, $return_string = true, $validations = []) {
        $style = $this->get_title_sizes($fields);
        $title = (!empty($fields['title'])) ? $fields['title'] : '';
        $heading = (!empty($fields['heading'])) ? $fields['heading'] : 'span';
        
        $styles = [];
        $style[] = (!empty($fields['title_color'])) ? 'color: '.$fields['title_color'] : 'color: #3a96e0';
        $style[] = (!empty($fields['font_weight'])) ? '--font-weight: '.$fields['font_weight'] : '--font-weight: 500';

        if (is_array($validations) && !isset($validations['unaligned']) || (isset($validations['unaligned']) && $validations['unaligned'] == false)) {
            $style[] = (!empty($fields['title_align'])) ? 'justify-content: '.$fields['title_align'] : 'justify-content: left';
        }

        $style[] = (!empty($fields['title_color_shadow'])) ? 'text-shadow: 0px 1px 1px '.$fields['title_color_shadow'] : 'text-shadow: 0px 1px 1px #03467d';
        $style[] = (!empty($fields['padding'])) ? 'padding-bottom: '.$fields['padding'].'rem' : 'padding-bottom: 0';
    
        if (count($style) > 0 && $return_string) {
            $styles = implode('; ', $style).';';
        } else {
            $styles = $style;
        }
    
        return [$heading, $title, $styles];
    }

    public function get_heading($fields, $type) {
        $style = $this->get_title_sizes($fields);

        if ($type == 'separator') {
            $heading = (!empty($fields['separator']['tag'])) ? $fields['separator']['tag'] : 'span';
            $separator = [];
            $separator[] = (!empty($fields['separator']['padding'])) ? 'padding-bottom: '.$fields['separator']['padding'].'rem' : 'padding-bottom: 0';
            $separator[] = (!empty($fields['separator']['text_align'])) ? '--justify: '.$fields['separator']['text_align'] : '--justify: left';
            $separator[] = (!empty($fields['separator']['border'])) ? '--border-size: '.$fields['separator']['border'].'px' : '--border-size: 5px';
            $separator[] = (!empty($fields['separator']['border_color'])) ? '--border-color: '.$fields['separator']['border_color'] : '--border-color: #000000';

            $separator_style = implode('; ', $separator).';';

            return [$heading, $separator_style];
        } else {
            $titles = [];
            $titles = $this->get_title_sizes($fields);
            
            $title = (!empty($fields['heading_text'])) ? $fields['heading_text'] : '';
            $titles[] = (!empty($fields['title_color'])) ? 'color: '.$fields['title_color'] : 'color: #000000';
            $titles[] = (!empty($fields['font_weight'])) ? '--font-weight: '.$fields['font_weight'] : '--font-weight: 500';

            if (!empty($fields['title_color_shadow'])) {
                $titles[] = 'text-shadow: 0px 1px 1px '.$fields['title_color_shadow'];
            }

            $titles_style = implode('; ', $titles).';';

            return [$title, $titles_style];
        }
    }
    
    public function get_title_sizes($fields) {
        $size = (!empty($fields['size'])) ? $fields['size'] : 3;
        $size_lg = (!empty($fields['size_lg'])) ? $fields['size_lg'] : null;
        $size_md = (!empty($fields['size_md'])) ? $fields['size_md'] : null;
        $size_sm = (!empty($fields['size_sm'])) ? $fields['size_sm'] : null;
    
        $style = [];
        
        if (!empty($size) || !empty($size_lg) || !empty($size_md) || !empty($size_sm)) {
            if (!empty($size)) {
                $last = $size;
                $style[] = '--font-size: '.$size.'rem';
                $style[] = '--line-height: '.(intval($size) + 0.5).'rem';
            } else {
                $last = 3;
                $style[] = '--font-size-lg: '.$last.'rem';
                $style[] = '--line-height-lg: '.($last + 0.5).'rem';
            }
    
            if (!empty($size_lg)) {
                $last = $size_lg;
                $style[] = '--font-size-lg: '.$size_lg.'rem';
                $style[] = '--line-height-lg: '.(intval($size_lg) + 0.5).'rem';
            } else {
                $style[] = '--font-size-lg: '.$last.'rem';
                $style[] = '--line-height-lg: '.($last + 0.5).'rem';
            }
    
            if (!empty($size_md)) {
                $last = $size_md;
                $style[] = '--font-size-md: '.$size_md.'rem';
                $style[] = '--line-height-md: '.(intval($size_md) + 0.5).'rem';
            } else {
                $style[] = '--font-size-md: '.$last.'rem';
                $style[] = '--line-height-md: '.($last + 0.5).'rem';
            }
            
            if (!empty($size_sm)) {
                $style[] = '--font-size-sm: '.$size_sm.'rem';
                $style[] = '--line-height-sm: '.(intval($size_sm) + 0.5).'rem';
            } else {
                $style[] = '--font-size-sm: '.$last.'rem';
                $style[] = '--line-height-sm: '.($last + 0.5).'rem';
            }
        }
    
        return $style;
    }

    public function get_cache_name($block_name, $post_id, $block_id, $dir = false) {
        $cache_name = $block_name.'-'.$post_id.'-'.$block_id.$this->cache_suffix;

        if (!$dir) {
            return $cache_name;
        }

        return $this->cache_dir.$cache_name;
    }

    public function set_cache_file($block_name, $cache_file, $data = null) {
        $file = New StdClass();
        $file->code = 200;
        $file->message = null;
        $file->cache_file = null;

        if (!file_exists($this->cache_dir)) {
            try {
                mkdir($this->cache_dir);
            } catch (Exception $exception) {
                if (file_exists($this->cache_dir)) {
                    unlink($this->cache_dir);
                }

                $error = $this->get_api_error('create_directory', ['block_name' => $block_name]);
                $file->code = 'create_directory';
                $file->message = $error;

                return $file;
            }
        }

        try {
            $cache = fopen($cache_file, "w");

            if (!empty($data)) {
                fwrite($cache, serialize($data));
            }

            fclose($cache);
        } catch (Exception $exception) {
            if (file_exists($cache_file)) {
                unlink($cache_file);
            }

            $error = $this->get_api_error('create_cache', ['block_name' => $block_name]);
            $file->code = 'create_cache';
            $file->message = $error;

            return $file;
        }

        $file->cache_file = $cache_file;

        return $file;
    }

    public function clear_cache($block_name, $post_id) {
        $file = New StdClass();
        $file->code = 200;
        $file->message = null;

        if (!file_exists($this->cache_dir)) {
            return $file;
        }

        $cache_list = scandir($this->cache_dir);

        $files_delete = array_map(function($cache) use ($block_name, $post_id) {
            $is_delete = strpos($cache, $block_name.'-'.$post_id.'-block-');

            if ($is_delete === 0) {
                return $cache;
            }

            return false;
        }, $cache_list);
        
        $files_delete = array_filter($files_delete);

        if (count($files_delete) > 0) {
            foreach ($files_delete as $delete) {
                try {
                    unlink($this->cache_dir.$delete);
                } catch (Exception $exception) {
                    $this->get_api_error('delete_cache', [
                        'post_id' => $post_id,
                        'block_name' => $block_name,
                        'cahe_file' => $this->cache_dir.$delete,
                        'exception' => $exception->getMessage(),
                    ]);

                    $file->code = 'delete_cache';
                }
            }
        }

        return $file;
    }

    public function get_api_data($block_name, $cache_file, $attibutes = []) {
        $data = new StdClass();
        $data->json = '';
        $data->message = '';
        $cache_exists = false;
        $cache_time_out = false;
        $cache_file = $this->cache_dir.$cache_file;

        $disable_cache = get_field('rdg_blocks_disable_block_cache', 'option');
        $block_disable = get_field('rdg_blocks_block_disable', 'option');

        if ((!is_user_logged_in() && $disable_cache == 'none') || (!is_user_logged_in() && $disable_cache == 'active' && $block_disable != $block_name)) {
            $cache_exists = true;

            if (!file_exists($cache_file)) {
                $error = $this->get_api_error('load_cache', [
                    'block_name' => $block_name,
                    'cache_file' => $cache_file,
                ]);

                $cache_exists = false;
            }

            if ($cache_exists) {
                $cache_refresh = (isset($attibutes['cache_refresh']) && !empty($attibutes['cache_refresh'])) 
                    ? intval($attibutes['cache_refresh']) : 1;
            
                $cache_time = ((time() - filemtime($cache_file)) / 60) / 60;
                //$cache_time = 50;
                if (($cache_time < $cache_refresh)) {
                    $cache = file_get_contents($cache_file);
                    $data->json = unserialize($cache);
        
                    return $data;
                } else {
                    $cache_time_out = true;
                }
            }
        }

        $items = (isset($attibutes['items']) && !empty($attibutes['items'])) 
            ? intval($attibutes['items']) : 10;
        $request = (isset($attibutes['request']) && !empty($attibutes['request'])) 
            ? $attibutes['request'] : '';
        $request_method = (isset($attibutes['method']) && !empty($attibutes['method'])) 
            ? $attibutes['method'] : 'GET';
        $request_headers = (isset($attibutes['headers']) && !empty($attibutes['headers'])) 
            ? $attibutes['headers'] : [];

        $response_json = '';
        $response = $this->get_api_request($request, $request_method, $request_headers);

        if ($response['http_code'] == 200) {
            $response_json = $this->is_json($response['data']);

            if ($response_json != null) {
                $data->json = $response_json;

                if ((!is_user_logged_in() && $disable_cache == 'none') || (!is_user_logged_in() && $disable_cache == 'active' && $block_disable != $block_name)) {
                    $file = $this->set_cache_file($block_name, $cache_file, $response_json);

                    if ($file->cache_file == null) {
                        $data->message = $this->get_api_error('create_cache', ['block_name' => $block_name]);

                        return $data;
                    } else {
                        if ($cache_time_out) {
                            $data->message = $this->get_api_error(200, ['block_name' => $block_name]);
                        }
                    }
                }

                return $data;
            }

            $response['http_code'] = 'json_response';
        }

        $error = $this->get_api_error($response['http_code'], [
            'block_name' => $block_name,
            'request' => $request,
            'response_json' => $response_json
        ]);

        $data->message = $error;
        
        return $data;
    }

    public function get_api_data_ajax($block_name, $attibutes = []) {
        $data = new StdClass();
        $data->json = '';
        $data->message = '';

        $items = (isset($attibutes['items']) && !empty($attibutes['items'])) 
            ? intval($attibutes['items']) : 10;
        $request = (isset($attibutes['request']) && !empty($attibutes['request'])) 
            ? $attibutes['request'] : '';
        $request_method = (isset($attibutes['method']) && !empty($attibutes['method'])) 
            ? $attibutes['method'] : 'GET';
        $request_headers = (isset($attibutes['headers']) && !empty($attibutes['headers'])) 
            ? $attibutes['headers'] : [];

        $response_json = '';
        $response = $this->get_api_request($request, $request_method, $request_headers);

        if ($response['http_code'] == 200) {
            $response_json = $this->is_json($response['data']);

            if ($response_json != null) {
                $data->json = $response_json;

                return $data;
            }

            $response['http_code'] = 'json_response';
        }

        $error = $this->get_api_error($response['http_code'], [
            'block_name' => $block_name,
            'request' => $request,
            'response_json' => $response_json
        ]);

        $data->message = $error;
        
        return $data;
    }

    public function get_api_request($request, $method, $headers = []) {
        $response = [];

        $curl = curl_init();

        curl_setopt_array($curl, [
            CURLOPT_URL => $request,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => $headers,
        ]);

        if (!PLATFORM) {
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        }

        $response['data']= curl_exec($curl);
        $response['http_code'] = curl_getinfo($curl, CURLINFO_HTTP_CODE);

        curl_close($curl);
        
        return $response;
    }

    public function get_blocks_caching($blocks, $post, $content) {
        $i = 0;
        $blocks_caching = [];

        foreach ($blocks as $block) {
            if ($block->is_caching() && is_array($post) && count($post) > 0 && isset($post['_acf_nonce'])) {
                $block_name = $block->get_block_name();

                $block_name_exp_init = '<!-- wp:'.str_replace('/', '\/', 'acf/'.$block_name);
                $blocks_count = preg_match_all('/'.$block_name_exp_init.'/', $content, $blocks_exp, PREG_OFFSET_CAPTURE);

                if ($blocks_count > 0) {
                    foreach ($blocks_exp[0] as $block_exp) {
                        $clear_block_init = substr($content, $block_exp[1], strlen($content));
                        preg_match('/\/-->/', $clear_block_init, $clear_block_end, PREG_OFFSET_CAPTURE);
                        $block_content = substr($clear_block_init, 0, $clear_block_end[0][1]).'/-->';
                        $block_parse = parse_blocks($block_content);
                        $block_attrs = $block_parse[0]['attrs'];

                        if (!isset($block_attrs['data']['source']) || $block_attrs['data']['source'] == SOURCE_DATA_API) {
                            $name = $block_attrs['name'];

                            if (substr($name, 0, 4) == 'acf/') {
                                $name = substr($name, 4, strlen($name));
                            }

                            $save = true;
                            foreach ($blocks_caching as $block_exist) {
                                if ($block_exist['custom_id'] == $block_attrs['data']['custom_id']) {
                                    $save = false;
                                    break;
                                }
                            }

                            if ($save) {
                                $blocks_caching[$i] = [
                                    'name' => $name,
                                    'custom_id' => $block_attrs['data']['custom_id'],
                                    'items' => (isset($block_attrs['data']['number_of_items'])) ? $block_attrs['data']['number_of_items'] : null,
                                ];

                                $rdgb = Rdg_Blocks::instance();
                                $current_block = $rdgb->settings->get_block($block_name);
                                $api_params = $current_block->get_api_params();

                                $transform = '';
                                $to_array = '';
                                $array_attributes = [];

                                if (count($api_params) > 0) {
                                    foreach ($api_params as $array_key => $field_name) {
                                        if ($array_key == '_to_transform_') {
                                            $transform = $api_params['_to_transform_'];
                                            unset($api_params['_to_transform_']);

                                            continue;
                                        }

                                        if ($array_key == '_to_array_') {
                                            $to_array = $api_params['_to_array_'];
                                            unset($api_params['_to_array_']);

                                            continue;
                                        }

                                        $array_attributes[$array_key] = isset($block_attrs['data'][$field_name]) ? $block_attrs['data'][$field_name] : '';
                                    }

                                    $transform_result = null;
                                    if (is_array($transform)) {
                                        $params = [];

                                        foreach ($transform['params'] as $param_name) {
                                            if (isset($block_attrs['data'][$param_name])) {
                                                $is_date = false;
                                                if (isset($transform['fields_date'])) {
                                                    if (in_array($param_name, $transform['fields_date'])) {
                                                        $is_date = true;
                                                    }
                                                }

                                                if ($is_date) {
                                                    $params[] = $this->get_valid_date($block_attrs['data'][$param_name]);
                                                } else {
                                                    $params[] = $block_attrs['data'][$param_name];
                                                }
                                            } else {
                                                $params[] = '';
                                            }
                                        }

                                        $transform_result = call_user_func_array(array($current_block, $transform['function']), $params);
                                    }

                                    if ($transform_result !== null) {
                                        $array_attributes[$transform['key']] = $transform_result;
                                    }

                                    $to_array_result = null;
                                    if (is_array($to_array)) {
                                        for ($j = 0; $j < $block_attrs['data'][$to_array['key']]; $j++) { 
                                            $prefix = $to_array['key'].'_'.$j.'_';

                                            foreach ($to_array['fields'] as $field_array) {
                                                $field_name = $prefix.$field_array;
                                                $to_array_result[$j][$field_array] = $block_attrs['data'][$field_name];
                                            }
                                        }
                                    }

                                    if ($to_array_result !== null) {
                                        $array_attributes[$to_array['key']] = $to_array_result;
                                    }
                                }

                                $blocks_caching[$i]['api_params'] = $array_attributes;

                                $i++;
                            }
                        }
                    }
                }
            }
        }

        return $blocks_caching;
    }

    public function get_valid_date($date) {
        if (substr_count($date, '-') == 2 && strlen($date) == 10) {
            return $date;
        }

        if (!strpos($date, '-') && strlen($date) == 8) {
            if (checkdate(intval(substr($date,4,2)), intval(substr($date,6,2)), intval(substr($date,0,4)))) {
                return substr($date,0,4).'-'.substr($date,4,2).'-'.substr($date,6,2);
            }
        }

        return $date;
    }

    public function is_json($string) {
        $encode = json_decode($string, true);
        $response = (json_last_error() === JSON_ERROR_NONE) ? $encode : null;

        return $response;
    }

    public function get_api_error($error, $attributes = null) {
        if ($error == 0) {
            $message = 'Invalid or unavailable URL.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 200) {
            error_log('Block: '. $attributes['block_name'].'. The cache was updated correctly.');

            return;
        }

        if ($error == 404) {
            $message = 'Resource not found.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 401) {
            $message = 'Not authorized.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }
        
        if ($error == 'json_response') {
            $message = 'Invalid data format.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'api_request') {
            $message = 'The request could not be processed.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'create_cache') {
            $message = 'Error trying to create cache.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'load_cache') {
            $message = 'Error trying to load cache.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'delete_cache') {
            $message = 'An error occurred while trying to clear the cache.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'refresh_cache') {
            $message = 'Error trying to update cache.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'create_directory') {
            $message = 'Error trying to create directory.';
            error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        $message = 'The data could not be accessed, please try again later.';
        error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

        return $message;
    }

    public function get_menus() {
        global $rdgb;
        $menus = [];
        $blocks = $rdgb->settings->get_blocks();

        foreach ($blocks as $block) {
            if ($block->is_config()) {
                $config = $block->get_config();
                $menus[$config['order']] = $config;
            }
        }

        ksort($menus);

        return $menus;
    }

    public function init_redis() {
        global $wp_object_cache;

        if (isset($wp_object_cache->redis) && $wp_object_cache->redis instanceof \Redis) {
            return true;
        }

        return false;
    }

    public function is_redis_active() {
        return $this->redis_cache;
    }

    public function set_redis_group($group = '') {
        $this->redis_cache_group = $group;
    }

    public function set_redis($key, $data, $expire = 0) {
        wp_cache_set($key, $data, $this->redis_cache_group, $expire);

        return true;
    }

    public function get_redis($key) {
        return wp_cache_get($key, $this->redis_cache_group);
    }

    public function update_redis($key, $data, $expire = 0) {
        wp_cache_replace($key, $data, $this->redis_cache_group, $expire);

        return true;
    }

    public function delete_redis($key) {
        wp_cache_delete($key, $this->redis_cache_group);

        return true;
    }

    public function get_image_source($url_image, $attributes = [])
    {
        $baseURL = get_bloginfo('url');
        //Force WPML to use the English version URL for images
        global $sitepress;
        if (isset($sitepress)) {
            $current_language = $sitepress->get_current_language();
            if ($current_language == 'es' || stripos($baseURL, "/es/") !== false) {
                $baseURL = str_ireplace("/es/", "", $baseURL);
            }
        }

        $alt_image = '';

        if (!file_exists($this->cache_dir)) {
            try {
                mkdir($this->cache_dir);
            } catch (Exception $exception) {
                error_log(print_r([
                    'message' => 'Error: Creating the cache directory.',
                    'directory' => $this->cache_dir,
                    'exception' => $exception->getMessage(),
                ], true));

                return ['url' => $url_image, 'alt' => $alt_image];
            }
        }

        if (!file_exists($this->cache_dir . 'images')) {
            try {
                mkdir($this->cache_dir . 'images');
            } catch (Exception $exception) {
                error_log(print_r([
                    'message' => 'Error: Creating the image directory.',
                    'directory' => $this->cache_dir . 'images',
                    'exception' => $exception->getMessage(),
                ], true));

                return ['url' => $url_image, 'alt' => $alt_image];
            }
        }

        if (!PLATFORM) {
            $basePath = '/wp-content/uploads/rdg-blocks/images/';
        } else {
            $basePath = '/app/uploads/rdg-blocks/images/';
        }

        try {
            $image_file = $this->get_image_name($url_image, $attributes['image_alt']);
            $alt_image = ($attributes['logo_label']) ? $image_file['alt'] . ' Logo' : $image_file['alt'];

            $name_image = $image_file['name'] . '.' . $image_file['extension'];
            $image = $this->cache_dir . 'images/' . $name_image;
            $new_image = $baseURL . $basePath . $name_image;

        } catch (Exception $exception) {
            error_log(print_r([
                'message' => 'Error: Creating the image name.',
                'url_image' => $url_image,
                'exception' => $exception->getMessage(),
            ], true));

            return ['url' => $url_image, 'alt' => $alt_image];
        }

        $image_reducer = $this->cache_dir . 'images/' . $image_file['name'] . '.webp';
        $new_image_reducer = $baseURL . $basePath . $image_file['name'] . '.webp';

        if (file_exists($image_reducer)) {
            return ['url' => $new_image_reducer, 'alt' => $alt_image];
        } else {
            if ($this->is_install_shortpixel() && $this->is_active_shortpixel()) {
                $this->add_image_reducer([$url_image]);
            }
        }

        if (file_exists($image)) {
            return ['url' => $new_image, 'alt' => $alt_image];
        } else {
            try {
                copy($url_image, $image);

                return ['url' => $new_image, 'alt' => $alt_image];
            } catch (Exception $exception) {
                if (file_exists($image)) {
                    unlink($image);
                }

                error_log(print_r([
                    'message' => 'Error: creating the image.',
                    'image' => $image,
                    'url_image' => $url_image,
                    'exception' => $exception->getMessage(),
                ], true));
            }
        }

        return ['url' => $url_image, 'alt' => $alt_image];
    }

    public function create_image_reducer($new_image) {
        if (!file_exists($this->cache_dir.'images')) {
            try {
                mkdir($this->cache_dir.'images');
            } catch (Exception $exception) {
                error_log(print_r([
                    'message' => 'Error: Creating the image directory.',
                    'directory' => $this->cache_dir.'images',
                    'exception' => $exception->getMessage(),
                ], true));

                return false;
            }
        }

        try {
            $name_image = $new_image['name'].'.webp';
            $image = $this->cache_dir.'images/'.$name_image;

            if (!file_exists($image)) {
                copy($new_image['reducer_url'], $image);
            }
        } catch (Exception $exception) {
            error_log(print_r([
                'message' => 'Error: Creating the image reducer.',
                'new_image' => $new_image,
                'exception' => $exception->getMessage(),
            ], true));

            return false;
        }

        return true;
    }

    public function get_image_name($url_image, $alt_image = '') {
        $alt = (!empty($alt_image)) ? $alt_image : '';
        $name = '';
        $extension = '';

        if (empty($url_image) || strpos($url_image, '/') == false) {
            return ['alt' => $alt, 'name' => $name, 'extension' => $extension];
        }

        $url_parts = explode('/', $url_image);

        if (is_array($url_parts) && count($url_parts) > 0) {
            $image = $url_parts[count($url_parts)-1];

            if (strpos($image, '.') == false) {
                return ['alt' => $alt, 'name' => $name, 'extension' => $extension];
            }

            $image_parts = explode('.', $image);
            $extension = strtolower($image_parts[count($image_parts) - 1]);
            array_pop($image_parts);

            if (count($image_parts) == 1) {
                $name = strtolower($image_parts[0]);
            } else {
                $name = strtolower(implode('-', $image_parts));
            }

            $alt = (!empty($alt_image)) ? $alt_image : str_replace(['-', '_'], ' ', $name);
        }

        return ['alt' => $alt, 'name' => $name, 'extension' => $extension];
    }

    public function is_install_shortpixel() {
        if (in_array('shortpixel-image-optimiser/wp-shortpixel.php', apply_filters('active_plugins', get_option('active_plugins')))) {
            return true;
        }
        
        return false;
    }

    public function is_active_shortpixel() {
        $short_pixel = (isset(get_field('rdg_resource_short_pixel_group', 'option')['short_pixel_active']))
            ? get_field('rdg_resource_short_pixel_group', 'option')['short_pixel_active']
            : 'none';
        
        return ($short_pixel == 'active') ? true : false;
    }

    public function get_max_chunks_shortpixel() {
        $max_chunks = (isset(get_field('rdg_resource_short_pixel_group', 'option')['max_chunks']))
            ? intval(get_field('rdg_resource_short_pixel_group', 'option')['max_chunks'])
            : 10;
        
        return $max_chunks;
    }

    public function get_redis_key_queue_shortpixel() {
        return 'short_pixel_reducer_queue';
    }

    public function add_image_reducer($array_images = []) {
        try {
            $images_queue = [];
            $key = $this->get_redis_key_queue_shortpixel();

            if ($this->init_redis()) {
                $this->set_redis_group(REDIS_GROUP_BLOCKS);
                $serialized_images = $this->get_redis($key);
        
                if (!empty($serialized_images)) {
                    $images_queue = unserialize($serialized_images);
                }

                foreach ($array_images as $new_image) {
                    if (!in_array($new_image, $images_queue)) {
                        $images_queue[] = $new_image;
                    }
                }

                $this->set_redis($key, serialize($images_queue));
            } else {
                error_log(print_r([
                    'message' => 'RDG Blocks: Redis needs to be enabled to handle image queue.',
                    'array_images' => $array_images
                ], true));
            }
        } catch (\Exception $exection) {
            error_log(print_r([
                'exception' => $exection->getMessage(),
                'array_images' => $array_images
            ], true));
        }
    }

    public function get_key_shortpixel() {
        return get_option('wp-short-pixel-apiKey');
    }

    public function get_url_shortpixel() {
        return 'https://api.shortpixel.com/v2/reducer.php';
    }

    public function get_sporst_categories_options($is_sub_title = false) {
        $sport_titles = [];
        $key = 'rdg_blocks_sports_categories_select_option';

        if ($this->init_redis()) {
            $this->set_redis_group(REDIS_GROUP_BLOCKS);
            $data_titles = $this->get_redis($key);
    
            if (!empty($data_titles)) {
                $unserialize_data = unserialize($data_titles);

                if (is_array($unserialize_data) && count($unserialize_data) > 0) {
                    return $unserialize_data;
                }
            }
        }

        $titles = get_field('sports_categories', 'option');

        if (is_array($titles) && count($titles) > 0) {
            foreach ($titles as $title) {
                if (is_array($title['categories']) && count($title['categories']) > 0 && $is_sub_title) {
                    $sub_titles = [];
                    $sub_titles[$title['sport_id']] = $title['sport_title'] .' - '. __('ANY CATEGORY');

                    foreach ($title['categories'] as $sub_title) {
                        $sub_titles[$title['sport_id'].'-'.$sub_title['category_id']] = $sub_title['category_title'];
                    }
                } else {
                    $sub_titles = $title['sport_title'];
                }

                if (is_array($sub_titles)) {
                    $sport_titles[$title['sport_title']] = $sub_titles;
                } else {
                    $sport_titles[$title['sport_id']] = $sub_titles;
                }
            }

            if ($this->init_redis() && is_array($sport_titles) && count($sport_titles) > 0) {
                $this->set_redis($key, serialize($sport_titles), REDIS_TIMEOUT);
            }
        }

        return $sport_titles;
    }

    public function get_sporst_categories_titles($is_sub_title = false) {
        $sport_titles = [];
        $key = 'rdg_blocks_sports_categories';
        
        if ($this->init_redis()) {
            $this->set_redis_group(REDIS_GROUP_BLOCKS);
            $data_titles = $this->get_redis($key);
    
            if (!empty($data_titles)) {
                $unserialize_data = unserialize($data_titles);

                if (is_array($unserialize_data) && count($unserialize_data) > 0) {
                    return $unserialize_data;
                }
            }
        }

        $titles = get_field('sports_categories', 'option');
        
        if (is_array($titles) && count($titles) > 0) {
            foreach ($titles as $title) {
                if (is_array($title['categories']) && count($title['categories']) > 0 && $is_sub_title) {
                    $sport_titles[$title['sport_id']] = $title['sport_title'];

                    foreach ($title['categories'] as $sub_title) {
                        $sport_titles[$title['sport_id'].'-'.$sub_title['category_id']] = $title['sport_title'].' | '.$sub_title['category_title'];
                    }
                } else {
                    $sport_titles[$title['sport_id']] = $title['sport_title'];
                }
            }

            if ($this->init_redis() && is_array($sport_titles) && count($sport_titles) > 0) {
                $this->set_redis($key, serialize($sport_titles), REDIS_TIMEOUT);
            }
        }

        return $sport_titles;
    }

    public function get_sporst_parts_options($is_sub_title = false) {
        $sport_titles = [];
        $key = 'rdg_blocks_sports_parts_select_option';

        if ($this->init_redis()) {
            $this->set_redis_group(REDIS_GROUP_BLOCKS);
            $data_titles = $this->get_redis($key);
    
            if (!empty($data_titles)) {
                $unserialize_data = unserialize($data_titles);

                if (is_array($unserialize_data) && count($unserialize_data) > 0) {
                    return $unserialize_data;
                }
            }
        }

        $titles = get_field('sports_categories', 'option');

        if (is_array($titles) && count($titles) > 0) {
            foreach ($titles as $title) {
                if (is_array($title['parts']) && count($title['parts']) > 0 && $is_sub_title) {
                    $sub_titles = [];
                    $sub_titles[$title['sport_id']] = $title['sport_title'] .' - '. __('ANY PARTS');

                    foreach ($title['parts'] as $sub_title) {
                        $sub_titles[$title['sport_id'].'-'.$sub_title['part_id']] = $sub_title['part_title'];
                    }
                } else {
                    $sub_titles = $title['sport_title'];
                }

                if (is_array($sub_titles)) {
                    $sport_titles[$title['sport_title']] = $sub_titles;
                } else {
                    $sport_titles[$title['sport_id']] = $sub_titles;
                }
            }

            if ($this->init_redis() && is_array($sport_titles) && count($sport_titles) > 0) {
                $this->set_redis($key, serialize($sport_titles), REDIS_TIMEOUT);
            }
        }

        return $sport_titles;
    }

    function rdg_pagination($current, $total) {
        $big = 999999999; // need an unlikely integer

        $pagination =  paginate_links([
            'base' => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
            'format' => '/page/%#%',
            'current' => (int) $current,
            'total' =>  (int) $total,
            'type' => 'array' 
        ]);

        echo '<nav><ul class="pagination">';

        foreach ($pagination ?? array() as $element) {
            $dom = new DomDocument();
            $dom->loadHTML($element);
            $page = '';

            foreach($dom->getElementsByTagName('a') as $a) {
                $parts = array_filter(explode('/', $a->getAttribute('href')), 'strlen');
                $page = $parts[count($parts)];
            }

            if (strpos($page, '=')) {
                $page = explode('=', $page)[1];
            }

            echo '<li class="page-item ">' . str_replace('class="', 'data-page="'.$page.'" class="page-link ', $element) . '</li>';
        }

        echo '</ul></nav>';
    }

    function rdg_debug_request($api_attributes) {
        if (get_field('rdg_blocks_debug_request', 'options') != 'active') return false;

        if (is_user_logged_in() && current_user_can('administrator') && isset($api_attributes['request']) && !empty($api_attributes['request'])) {
            return true;
        }

        return false;
    }

    public function validate_fields($fields, $data) {
        $validate = true;

        if (is_array($fields) && count($fields) > 0) {
            foreach ($fields as $field => $validations) {
                if (in_array('required', $validations) && !isset($data[$field])) {
                    $validate = false;
                }

                if (in_array('notnull', $validations) && isset($data[$field]) && empty($data[$field])) {
                    $validate = false;
                }

                if (!$validate) {
                    break;
                }
            }
        }

        return $validate;
    }

    public function rdg_debug_cache($cache_file) {
        if (empty($cache_file)) return false;
        if (get_field('rdg_blocks_debug_cache', 'options') != 'active') return false;

        $file_exists = file_exists($this->cache_dir.$cache_file);

        if (is_user_logged_in() && current_user_can('administrator') && $file_exists) {
            return true;
        }

        return false;
    }

    public function rdg_api_request($url) { 
        $response = wp_remote_get($url);
        
        if (wp_remote_retrieve_response_code($response) !== 200) {
            return null;
        }
        
        return json_decode(wp_remote_retrieve_body($response), true);
    }

    public function is_install_acfe() {
        if (in_array('acf-extended-pro/acf-extended.php', apply_filters('active_plugins', get_option('active_plugins')))) {
            return true;
        }
        
        return false;
    }
}
