<?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_DIR.$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 (!defined('BEDROCK') || !BEDROCK) {
            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 = 'Anerror_log 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];
            }
        }

        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 . RDGBLOCKS_BASE_PATH . $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 . RDGBLOCKS_BASE_PATH . $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 isInstallPlugin($plugin) {
        if (in_array($plugin, apply_filters('active_plugins', get_option('active_plugins')))) {
            return true;
        }
        
        return false;
    }

    public function isInstallAcfe() {
        if ($this->isInstallPlugin('acf-extended-pro/acf-extended.php')) {
            return true;
        }

        if ($this->isInstallPlugin('acf-extended/acf-extended.php')) {
            return true;
        }
        
        return false;
    }

    public function isInstallGeneratePress() {
        $current_theme = wp_get_theme();

        # Check if the active theme is generatePress
        if ('generatepress' == $current_theme->get('TextDomain')) {
            return true;
        }

        # Check if the active theme is a child of a generatePress theme
        if ('generatepress' == $current_theme->get('Template')) {
            return true;
        }
        
        return false;
    }

    public function getBlocksStylesLoad() {
        $i = 0;
        $blocks_load = [];

        $rdgb = Rdg_Blocks::instance();
        $blocks = $rdgb->settings->get_blocks();

        foreach ($blocks as $block) {
            if ($block->isStylesLoad()) {
                $blocks_load[$block->get_block_name()] = $block;
            }
        }

        return $blocks_load;
    }

    public function registerGeneratePressColors($colors, $saved_colors, $options) {
        $colors_new = [];
        foreach ($colors as $key => $color) {
            if (!in_array($color['slug'], $saved_colors)) {
                $colors_new[] = $color;
            }
        }

        if (is_array($colors_new) && count($colors_new) > 0) {
            $generatepress_colors = array_merge($options['global_colors'], $colors_new);
            $options['global_colors'] = $generatepress_colors;
            update_option('generate_settings', $options);
        }

        return $options;
    }

    public function getDefaultColors() {
        return [
            [
                'name' => __( 'Contrast', 'generatepress' ),
                'slug' => 'contrast',
                'color' => '#333333',
            ],
            [
                'name' => sprintf( __( 'Contrast %s', 'generatepress' ), '2' ),
                'slug' => 'contrast-2',
                'color' => '#555555',
            ],
            [
                'name' => sprintf( __( 'Contrast %s', 'generatepress' ), '3' ),
                'slug' => 'contrast-3',
                'color' => '#b4b4b4',
            ],
            [
                'name' => __( 'Base', 'generatepress' ),
                'slug' => 'base',
                'color' => '#f1f1f1',
            ],
            [
                'name' => sprintf( __( 'Base %s', 'generatepress' ), '2' ),
                'slug' => 'base-2',
                'color' => '#f5f5f5',
            ],
            [
                'name' => sprintf( __( 'Base %s', 'generatepress' ), '3' ),
                'slug' => 'base-3',
                'color' => '#eeeeee',
            ],
        ];
    }

    public function registerGeneratePressStyles($styles, $saved_styles, $options) {
        $styles = $this->setDefaultStylesFields($styles);

        $styles_new = [];
        foreach ($styles as $key => $style) {
            if (!in_array($style['customSelector'], $saved_styles)) {
                $styles_new[] = $style;
            }
        }

        if (is_array($styles_new) && count($styles_new) > 0) {
            $generatepress_styles = array_merge($options['typography'], $styles_new);
            $options['typography'] = $generatepress_styles;
            update_option('generate_settings', $options);
        }

        return $options;
    }

    public function setDefaultStylesFields($styles) {
        $default_fields = [
            'customSelector' => '',
            'fontFamily' => '',
            'fontWeight' => '',
            'textTransform' => '',
            'textDecoration' => '',
            'fontStyle' => '',
            'fontSize' => '',
            'fontSizeTablet' => '',
            'fontSizeMobile' => '',
            'lineHeight' => '',
            'lineHeightTablet' => '',
            'lineHeightMobile' => '',
            'letterSpacing' => '',
            'letterSpacingTablet' => '',
            'letterSpacingMobile' => '',
            'marginBottom' => '',
            'marginBottomTablet' => '',
            'marginBottomMobile' => '',
            'marginBottomUnit' => '',
        ];

        $new_styles = [];
        foreach ($styles as $style) {
            $set_styles = array_merge($default_fields, $style);
            $set_styles['selector'] = 'custom';
            $set_styles['module'] = 'core';
            $set_styles['group'] = 'other';
            $new_styles[] = $set_styles;
        }

        return $new_styles;
    }

    public function registerStylesCss($block, $styles) {
        $new_styles = [];
        foreach ($styles as $style) {
            if (!isset($style['customSelector']) || empty($style['customSelector'])) continue;

            $selector = $style['customSelector'];
            unset($style['customSelector']);
            
            $css_array = [];
            $css_array_tablet = [];
            $css_array_mobile = [];
            foreach ($style as $attribute => $value) {
                if (!$this->validAttribute($attribute)) continue;

                if (in_array($attribute, ['fontSizeTablet', 'lineHeightTablet', 'letterSpacingTablet'])) {
                    $tem_css_tablet = $this->convertAttribute($attribute, $value);
                    if (!empty($tem_css_tablet)) {
                        $css_array_tablet[] = $tem_css_tablet;
                    }

                    continue;
                }

                if (in_array($attribute, ['fontSizeMobile', 'lineHeightMobile', 'letterSpacingMobile'])) {
                    $tem_css_mobile = $this->convertAttribute($attribute, $value);
                    if (!empty($tem_css_mobile)) {
                        $css_array_mobile[] = $tem_css_mobile;
                    }

                    continue;
                }
                
                $tem_css = $this->convertAttribute($attribute, $value);
                if (!empty($tem_css)) {
                    $css_array[] = $tem_css;
                }
            }

            if (is_array($css_array) && count($css_array) > 0) {
                $new_styles[] = sprintf('%s { %s }', $selector,implode(' ', $css_array));
            }

            if (is_array($css_array_tablet) && count($css_array_tablet) > 0) {
                $new_styles[] = sprintf('@media (max-width: 1024px) { %s { %s }}', $selector,implode(' ', $css_array_tablet));
            }

            if (is_array($css_array_mobile) && count($css_array_mobile) > 0) {
                $new_styles[] = sprintf('@media (max-width: 768px) { %s { %s }}', $selector,implode(' ', $css_array_mobile));
            }
        }

        $block_name = $block->get_block_name();
        $css_file_block = $this->getCssFileBlock($block_name);

        if (empty($css_file_block)) {
           error_log(print_r([
                'message' => 'RDG Blocks / registerStylesCss: Block css file not found.',
                'block_name' => $block_name,
            ], true));

            return '';
        }

        $this->setCssFileBlock($css_file_block, $new_styles);
    }

    public function setCssFileBlock($css_file, $styles) {
        try {
            # Check if the block styles file exists
            $file_name = RDGBLOCKS_PLUGIN_DIR.'dist/'.$css_file;
            if (!file_exists($file_name)) {
               error_log(print_r([
                    'message' => 'RDG Blocks / setCssFileBlock: Block style file not found.',
                    'css_file' => $css_file,
                ], true));
    
                return;
            }

            # Get the content of the styles file
            $check_content_file = file_get_contents($file_name);

            # Clean old styles
            $clear_css = preg_replace('/\/\*open-auto-code\*\/[\s\S]+?\/\*close-auto-code\*\//', '', $check_content_file);
            
            # Update possible new styles in the block
            $spaces = (strlen($check_content_file) == strlen($clear_css)) ? "\n\n" : "";
            $css_new = $clear_css.$spaces."/*open-auto-code*/".implode(' ', $styles)."/*close-auto-code*/";
            file_put_contents($file_name, $css_new, LOCK_EX);
        } catch (\Exception $exception) {
           error_log(print_r([
                'message' => sprintf('RDG Blocks / setCssFileBlock: %s', $exception->getMessage()),
                'css_file' => $css_file,
                'styles' => $styles,
            ], true));
        }
    }

    public function getCssFileBlock($block_name) {
        try {
            if (!file_exists(RDGBLOCKS_PLUGIN_DIR.'dist/manifest.json')) {
               error_log(print_r([
                    'message' => 'RDG Blocks / getCssFileBlock: Manifest file not found.',
                    'block_name' => $block_name,
                ], true));
    
                return '';
            }
    
            $manifest = RDGBLOCKS_PLUGIN_DIR.'dist/manifest.json';
            $blocks_data = file_get_contents($manifest);
            $blocks_data_array = json_decode($blocks_data, true);

            if (is_array($blocks_data_array) && count($blocks_data_array) > 0) {
                if (isset($blocks_data_array[str_replace('-', '_', $block_name).'.css'])) {
                    return $blocks_data_array[str_replace('-', '_', $block_name).'.css'];
                }
            }
        } catch (\Exception $exception) {
           error_log(print_r([
                'message' => sprintf('RDG Blocks / getCssFileBlock: %s', $exception->getMessage()),
                'block_name' => $block_name,
            ], true));
        }

        return '';
    }

    public function convertAttribute($attribute, $value) {
        #Options: normal, bold, 100, 200, 300, 400, 500, 600, 700, 800, 900
        if ($attribute == 'fontWeight') {
            return sprintf('font-weight: %s;', $value);
        }

        #Options: uppercase, lowercase, capitalize, initial
        if ($attribute == 'textTransform') {
            return sprintf('text-transform: %s;', $value);
        }

        #Options: none, underline
        if ($attribute == 'textDecoration') {
            return sprintf('text-decoration: %s;', $value);
        }

        #Options: normal, italic, oblique, initial
        if ($attribute == 'fontStyle') {
            return sprintf('font-style: %s;', $value);
        }

        #Options: 15px, 2.5rem, 1.7em, 10%
        if (in_array($attribute, ['fontSize', 'fontSizeTablet', 'fontSizeMobile'])) {
            return sprintf('font-size: %s;', $value);
        }

        #Options: 15px, 2.5rem, 1.7em, 10%
        if (in_array($attribute, ['lineHeight', 'lineHeightTablet', 'lineHeightMobile'])) {
            return sprintf('line-height: %s;', $value);
        }

        #Options: 15px, 2.5rem, 1.7em, 10%
        if (in_array($attribute, ['letterSpacing', 'letterSpacingTablet', 'letterSpacingMobile'])) {
            return sprintf('letter-spacing: %s;', $value);
        }

        return '';
    }

    public function validAttribute($attribute) {
        return in_array($attribute, ['fontWeight', 'fontSize', 'fontSizeTablet', 'fontSizeMobile', 'textTransform', 
            'textDecoration', 'fontStyle', 'lineHeight', 'lineHeightTablet', 'lineHeightMobile', 'letterSpacing', 
        'letterSpacingTablet', 'letterSpacingMobile']);
    }

    public function getBaseColors() {
        return [
            ['name' => 'color-white','slug' => 'color-white','color' => '#FFFFFF'],
            ['name' => 'color-black','slug' => 'color-black','color' => '#111111'],
            ['name' => 'color-primary','slug' => 'color-primary','color' => '#3a96e0'],
            ['name' => 'color-primary-dark','slug' => 'color-primary-dark','color' => '#03467d'],
            ['name' => 'color-primary-dark-light','slug' => 'color-primary-dark-light','color' => '#0160ac'],
            ['name' => 'color-gray','slug' => 'color-gray','color' => '#F1F1F1'],
            ['name' => 'color-gray-line','slug' => 'color-gray-line','color' => '#CCC'],
            ['name' => 'color-danger','slug' => 'color-danger','color' => '#e11414'],
            ['name' => 'color-danger-dark','slug' => 'color-danger-dark','color' => '#891010'],
            ['name' => 'color-danger-light','slug' => 'color-danger-light','color' => '#fc6363'],
            ['name' => 'color-warning','slug' => 'color-warning','color' => '#e69305'],
            ['name' => 'color-warning-dark','slug' => 'color-warning-dark','color' => '#9f6809'],
            ['name' => 'color-warning-light','slug' => 'color-warning-light','color' => '#f5c776'],
            ['name' => 'color-success','slug' => 'color-success','color' => '#00bc00'],
            ['name' => 'color-success-dark','slug' => 'color-success-dark','color' => '#244d0e'],
            ['name' => 'color-success-light','slug' => 'color-success-light','color' => '#68f96e'],
        ];
    }
}
