<?php
if (!defined('ABSPATH')) {
    exit();
}
if (!class_exists('CCPWP_api_data')) {
    class CCPWP_api_data
    {

        /**
         * CCPWP_COINS_LIST  used for save 2500 coins list index Transient name.
         * COINS_LIST_TIME  used for save 2500 coins list index Transient TIME
         */
        const CCPWP_COINS_LIST = 'ccpw-all-gecko-coins';
        const COINS_LIST_TIME = 0;

        /**
         * CCPWP_GLOBAL_DATA used for GLOBAL data transient name.
         * GLOBAL_DATA_TIME used for GLOBAL data transient time.
         */
        const CCPWP_GLOBAL_DATA = 'cmc-global-data';
        const GLOBAL_DATA_TIME = 15 * MINUTE_IN_SECONDS;

        /**
         * CCPWP_MAIN_LIST_DATA used for save data using coingecko api.
         * MAIN_LIST_DATA_TIME used for save data using coingecko api transient time.
         */
        const CCPWP_MAIN_LIST_DATA = 'cmc-saved-coindata-';
        const MAIN_LIST_DATA_TIME = 5 * MINUTE_IN_SECONDS;

        /**
         * CCPWP_UNAVILABLE_DATA used for unavailable data transient name.
         */
        const CCPWP_UNAVILABLE_DATA = 'ccpwp-unavailable-coins';
        const CCPWP_UNAVILABLE_DATA_CMC = 'ccpwp-unavailable-coins-cmc';

        /**
         * CCPWP_REFRESH_COINS used for refresh the coins data.
         * REFRESH_COINS_TIME used for refresh the coins data transient time.
         */
        const CCPWP_REFRESH_COINS = 'ccpwp-ua-coins-refresh';
        const REFRESH_COINS_TIME = 5 * MINUTE_IN_SECONDS;

        /**
         * CCPWP_HISTORICAL_DATA used for historical data transient name.
         * HISTORICAL_DATA_TIME used for historical data transient time.
         */
        const CCPWP_HISTORICAL_DATA = 'historical-coingecko-data-';
        const HISTORICAL_DATA_TIME = 2 * HOUR_IN_SECONDS;

        /**
         * CCPWP_USD_CONVERSION used for coins fiat conversion transient name(common in all crypto plugins).
         * USD_CONVERSION_TIME used for coins fiat conversion transient time(common in all crypto plugins).
         */
        const CCPWP_USD_CONVERSION = 'cmc_usd_conversions';
        const USD_CONVERSION_TIME = 12 * HOUR_IN_SECONDS;

        /**
         * CCPWP_API_LIMIT used for save transient if api limit exceed.
         * API_LIMIT_TIME used for api limit exceed transient time.
         */
        const CCPWP_API_LIMIT = 'ccpw_api_limit';
        const API_LIMIT_TIME = 1 * HOUR_IN_SECONDS;

        /**
         * COINPAPRIKA_API_ENDPOINT
         *
         * Holds the URL of the coinpaprika API.
         *
         * @access public
         *
         */
        const COINPAPRIKA_API_ENDPOINT = 'https://api.coinpaprika.com/v1/';

        /**
         * CCPWP_COINMARKETCAP_API_ENDPOINT
         *
         * Holds the URL of the coins data API.
         *
         * @access public
         *
         */
        const CCPWP_COINMARKETCAP_API_ENDPOINT = 'https://pro-api.coinmarketcap.com/';
        /**
         * COINGECKO_API_ENDPOINT
         *
         * Holds the URL of the coingecko API.
         *
         * @access public
         *
         */

        const COINGECKO_API_ENDPOINT = 'https://api.coingecko.com/api/v3/';
        /**
         * OPENEXCHANGERATE_API_ENDPOINT
         *
         * Holds the URL of the openexchangerates API.
         *
         * @access public
         *
         */

        const OPENEXCHANGERATE_API_ENDPOINT = 'https://openexchangerates.org/api/latest.json?app_id=';

        public function __construct()
        {
            // self::CMC_API_ENDPOINT = 'https://apiv3.coinexchangeprice.com/v3/';
        }

        // Function to get the CoinGecko API key
        public static function get_coingecko_api_key() {
            $api_option = get_option("openexchange-api-settings");
            $api_key =(isset($api_option['coingecko_api'])) ? $api_option['coingecko_api'] : ""; // Default API key
            // Apply filter to allow changing the API key
            $api_key = apply_filters('coingecko_api_key', $api_key);
            return $api_key;
        }

        //Api selection function
        public static function ccpwp_get_selected_api_data($page = 1)
        {
            $api_option = get_option("openexchange-api-settings");
            $api_type = (isset($api_option['select_api'])) ? $api_option['select_api'] : "coingecko";
            if ($api_type == "coingecko") {
                return self::ccpwp_get_api_data($page);
            } else if ($api_type == "coinmarketcap") {
                return self::ccpwp_get_cmc_api_data($page);
            } else if ($api_type == "both_coingecko") {
                if (isset($api_option['coingecko_api']) && !empty($api_option['coingecko_api'])) {
                    return self::ccpwp_get_api_data($page);
                } else if (isset($api_option['coinmarketcap_api']) && !empty($api_option['coinmarketcap_api'])) {
                    return self::ccpwp_get_cmc_api_data($page);
                }

            } else if ($api_type == "both_coinmarketcap") {
                if (isset($api_option['coinmarketcap_api']) && !empty($api_option['coinmarketcap_api'])) {
                    return self::ccpwp_get_cmc_api_data($page);

                } else if (isset($api_option['coingecko_api']) && !empty($api_option['coingecko_api'])) {
                    return self::ccpwp_get_api_data($page);

                }

            }

        }
        //API selection for unavailable coins
        public static function ccpwp_get_selected_api_ua_data($coin_ids)
        {
            $api_option = get_option("openexchange-api-settings");
            $api_type = (isset($api_option['select_api'])) ? $api_option['select_api'] : "coingecko";
            if ($api_type == "coingecko") {
                return self::ccpwp_update_unavailable_coins_data($coin_ids);
            } else if ($api_type == "coinmarketcap") {
                return self::ccpwp_update_unavailable_coins_data_cmc($coin_ids);
            } else if ($api_type == "both_coingecko") {
                if (isset($api_option['coingecko_api']) && !empty($api_option['coingecko_api'])) {
                    return self::ccpwp_update_unavailable_coins_data($coin_ids);
                } else if (isset($api_option['coinmarketcap_api']) && !empty($api_option['coinmarketcap_api'])) {
                    return self::ccpwp_update_unavailable_coins_data_cmc($coin_ids);
                }

            } else if ($api_type == "both_coinmarketcap") {
                if (isset($api_option['coinmarketcap_api']) && !empty($api_option['coinmarketcap_api'])) {
                    return self::ccpwp_update_unavailable_coins_data_cmc($coin_ids);
                } else if (isset($api_option['coingecko_api']) && !empty($api_option['coingecko_api'])) {
                    return self::ccpwp_update_unavailable_coins_data($coin_ids);
                }

            }

        }

        //Api selection function for global data
        public static function ccpwp_select_historical_data_api($coin_id)
        {
            $api_option = get_option("openexchange-api-settings");
            $api_type = (isset($api_option['select_api'])) ? $api_option['select_api'] : "coingecko";
            if ($api_type == "coingecko") {
                return self::ccpw_coin_historical_data($coin_id);
            } else if ($api_type == "coinmarketcap") {
                return self::ccpwp_historical_coins_from_cmc_api($coin_id);
            } else if ($api_type == "both_coingecko") {
                if (isset($api_option['coingecko_api']) && !empty($api_option['coingecko_api'])) {
                    return self::ccpw_coin_historical_data($coin_id);
                } else if (isset($api_option['coinmarketcap_api']) && !empty($api_option['coinmarketcap_api'])) {
                    return self::ccpwp_historical_coins_from_cmc_api($coin_id);
                }

            } else if ($api_type == "both_coinmarketcap") {
                if (isset($api_option['coinmarketcap_api']) && !empty($api_option['coinmarketcap_api'])) {
                    return self::ccpwp_historical_coins_from_cmc_api($coin_id);

                } else if (isset($api_option['coingecko_api']) && !empty($api_option['coingecko_api'])) {
                    return self::ccpw_coin_historical_data($coin_id);

                }

            }

        }

        /*
        |-----------------------------------------------------------
        | Fetching data through CoinGecko API and save in database
        |-----------------------------------------------------------
         */
        public static function ccpwp_get_api_data($page = 1)
        {

            $data_cache_name = self::CCPWP_MAIN_LIST_DATA . $page;
            $ua_coins_name = self::CCPWP_UNAVILABLE_DATA;

            $ua_refresh_time = get_transient('ccpwp-ua-coins-refresh');
            $ua_coins_cache = get_option($ua_coins_name);
            $cache = get_transient($data_cache_name);
            $api_option = get_option("openexchange-api-settings");
            $coingecko_api_key = self::get_coingecko_api_key();
            $coingecko_api_cache_time = isset($api_option['select_cache_time']) ? (int) $api_option['select_cache_time'] : 10;

            if (!ccpwp_check_user()) {
                return;
            }

            // Avoid updating database if cache exist or CMC is active
            if (false != $cache || get_option('cmc-dynamic-links') != false) {
                return;
            }
            $coins = array();
            // $coin_list = ccpwp_get_allCoins();
            $api_url = ccpwp_get_api_end_point() . 'coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250&page=' . $page . '&sparkline=true&price_change_percentage=24h%2C7d%2C30d%2C1y&' . ccpwp_get_api_key_end_point() . '=' . $coingecko_api_key;
            //$api_url = 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250&page='.$page.'&sparkline=true&price_change_percentage=24h%2C7d%2C30d%2C1y';
            $request = wp_remote_get($api_url, array('timeout' => 300, 'sslverify' => true));
            if (is_wp_error($request)) {
                return false; // Bail early
            }

            $body = wp_remote_retrieve_body($request);
            $coins = json_decode($body);

            if (ccpwp_check_api_errors($coins)) {
                return self::ccpwp_get_api_data_backup();
            }
            $response = array();
            $coin_data = array();
            $db_coins = array();
            $coinid_list = array();
            if (isset($coins) && is_array($coins)) {
                ccpwp_track_coingecko_api_hit();
                foreach ($coins as $coin) {

                    // Ensure $coin is an object and properties exist
                    if (!is_object($coin)) {
                        continue;
                    }
                    // Skip coins with emoji in name, symbol, or coin_id
                    if (self::contains_emoji($coin->name ?? '') || self::contains_emoji($coin->symbol ?? '') || self::contains_emoji($coin->id ?? '')) {
                        continue;
                    }

                    $response['coin_id'] = sanitize_text_field($coin->id ?? '');
                    $response['name'] = sanitize_text_field($coin->name ?? '');
                    $response['symbol'] = strtoupper(sanitize_text_field($coin->symbol ?? ''));
                    $response['price'] = ccpwp_set_default_if_empty($coin->current_price);
                    $response['percent_change_24h'] = ccpwp_set_default_if_empty($coin->price_change_percentage_24h, 0);
                    $response['percent_change_1y'] = ccpwp_set_default_if_empty($coin->price_change_percentage_1y_in_currency, 0);
                    $response['percent_change_30d'] = ccpwp_set_default_if_empty($coin->price_change_percentage_30d_in_currency, 0);
                    $response['percent_change_7d'] = ccpwp_set_default_if_empty($coin->price_change_percentage_7d_in_currency, 0);
                    $response['market_cap'] = ccpwp_set_default_if_empty($coin->market_cap, 0);
                    $response['total_volume'] = ccpwp_set_default_if_empty($coin->total_volume);
                    $response['circulating_supply'] = ccpwp_set_default_if_empty($coin->circulating_supply);

                    $charts = array();
                    if (!empty($coin->sparkline_in_7d->price)) {
                        $x = 0;
                        foreach ($coin->sparkline_in_7d->price as $chart) {
                            if ($x % 6 === 0) {
                                if ($chart > 0.50) {
                                    $charts[] = number_format((float) $chart, 4, '.', '');
                                } else {
                                    $charts[] = number_format((float) $chart, 6, '.', '');
                                }
                            }
                            $x++;
                        }
                    }
                    $response['weekly_price_data'] = !empty($charts) ? serialize($charts) : null;

                    $response['logo'] = substr(sanitize_url($coin->image ?? ''), strpos($coin->image ?? '', "images") + 7);
                  
                    $coin_data[] = $response;
                    $db_coins[] = sanitize_text_field($coin->id ?? '');

                    $coinid_list[] = $coin->id;
                     // Save data in chunks of 50 to avoid memory issues
                     if (count($coin_data) >= 50) {
                        self::save_coin_data($coin_data);
                        $coin_data = array(); // Reset array for next chunk
                    }
                }
                // Save any remaining data that was not saved in the last chunk
                if (!empty($coin_data)) {
                    self::save_coin_data($coin_data);
                }
                if ($page == 1) {
                    update_option('ccpwp-available-coins', $db_coins, true);
                }
                // save all the coin id's udated through API by default
                //update_option( 'ccpw-default-coins', $default_coins , $coinid_list );
                set_transient($data_cache_name, date('H:s:i'), $coingecko_api_cache_time * MINUTE_IN_SECONDS);

            }

            // fetch other than 250 default coins
            if (false == $ua_refresh_time) {
                self::ccpwp_update_unavailable_coins_data($ua_coins_cache);
            }
        } // end of ccpwp_get_coin_gecko_data()

        /*
        |-----------------------------------------------------------
        | Fetching data through Coinpaprika API and save in database
        |-----------------------------------------------------------
         */
        public static function ccpwp_get_api_data_backup($page = 1)
        {

            $data_cache_name = self::CCPWP_MAIN_LIST_DATA . $page;

            $cache = get_transient($data_cache_name);
            $ua_coins_name = self::CCPWP_UNAVILABLE_DATA;

            $ua_refresh_time = get_transient('ccpwp-ua-coins-refresh');
            $ua_coins_cache = get_option($ua_coins_name);

            // Avoid updating database if cache exist or CMC is active
            if (false != $cache) {
                return;
            }
            $api_option = get_option("openexchange-api-settings");
            $coingecko_api_cache_time = isset($api_option['select_cache_time']) ? (int) $api_option['select_cache_time'] : 10;
            $coins = array();
            $request = wp_remote_get($api_url = self::COINPAPRIKA_API_ENDPOINT . 'tickers', array('timeout' => 300, 'sslverify' => true));
            if (is_wp_error($request)) {
                return false; // Bail early
            }

            $body = wp_remote_retrieve_body($request);
            $coins = json_decode($body, true);

            $response = array();
            $coin_data = array();
            $db_coins = array();
            $coinid_list = array();
            if (isset($coins) && $coins != "" && is_array($coins)) {
                foreach ($coins as $coin) {
                    if (ccpwp_coin_array($coin['id'])) {
                        $cp = ccpwp_set_default_if_empty($coin['quotes']['USD']['price'], 0.00);
                        $response['coin_id'] = ccpwp_coin_array($coin['id']);
                        // $response['rank'] = $coin['rank'];
                        $response['name'] = $coin['name'];
                        $response['symbol'] = strtoupper($coin['symbol']);
                        $response['price'] = $cp;
                        $response['percent_change_24h'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_change_24h']);
                        $response['percent_change_7d'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_change_7d']);
                        $response['percent_change_30d'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_change_30d']);
                        $response['percent_change_1y'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_change_1y']);
                        //  $response['high_24h'] = $cp*1.02;;
                        //  $response['low_24h'] =$cp*0.98;
                        $response['market_cap'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['market_cap'], 0);
                        $response['total_volume'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['volume_24h']);
                        $response['circulating_supply'] = ccpwp_set_default_if_empty($coin['circulating_supply']);
                        //  $response['ath'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['ath_price'],0);
                        //   $response['ath_date'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['ath_date']);
                        //   $response['ath_change_percentage'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_from_price_ath'],0);
                        $response['last_updated'] = gmdate('Y-m-d h:i:s');

                        $coin_data[] = $response;

                    }
                }
                $cmcDB = new ccpwp_database();

                $parts = null;
                $previous = 0;
                for ($i = 0; $i < 6; $i++) {
                    $now = $previous;
                    $parts = array_slice($coin_data, $now, $previous + 600);
                    $parts = ccpwp_objectToArray($parts);
                    $savedd = $cmcDB->ccpw_insert($parts);
                    $previous += 600;
                }

                // save all the coin id's udated through API by default
                //update_option( 'ccpw-default-coins', $default_coins , $coinid_list );
                set_transient($data_cache_name, date('H:s:i'), $coingecko_api_cache_time * MINUTE_IN_SECONDS);
                if (false == $ua_refresh_time) {
                    self::ccpwp_update_unavailable_coins_data($ua_coins_cache);
                }

            }

            //sleep($delay);
        } // end of ccpwp_get_coin_gecko_data_backup()

        /*
        |-----------------------------------------------------------
        | Fetching data through Coinmarketcap API and save in database
        |-----------------------------------------------------------
         */
        public static function ccpwp_get_cmc_api_data($page = 1)
        {
            $data_cache_name = self::CCPWP_MAIN_LIST_DATA . $page;
            $api_option = get_option("openexchange-api-settings");

            $cache = get_transient($data_cache_name);
            $api_type = (isset($api_option['select_api'])) ? $api_option['select_api'] : "coingecko";

            $ua_coins_name = ($api_type == "both_coinmarketcap" || $api_type == "coinmarketcap") ? self::CCPWP_UNAVILABLE_DATA_CMC : self::CCPWP_UNAVILABLE_DATA;

            $ua_refresh_time = get_transient('ccpwp-ua-coins-refresh');
            $ua_coins_cache = get_option($ua_coins_name);
            $numberoftokens = ($page == 1) ? $page : ($page - 1) * 200;

// Avoid updating database if cache exist or CMC is active
            if (false != $cache) {
                return;
            }

            $coingecko_api_cache_time = isset($api_option['select_cache_time']) ? (int) $api_option['select_cache_time'] : 10;
            $api_key = (isset($api_option['coinmarketcap_api']) && !empty($api_option['coinmarketcap_api'])) ? $api_option['coinmarketcap_api'] : '';

            $coins = array();
            $request = wp_remote_get(self::CCPWP_COINMARKETCAP_API_ENDPOINT . 'v1/cryptocurrency/listings/latest?start=' . $numberoftokens . '&limit=200&CMC_PRO_API_KEY=' . $api_key, array('timeout' => 120, 'sslverify' => true));
            if (is_wp_error($request)) {
                return false; // Bail early
            }

            $body = wp_remote_retrieve_body($request);
            $coins = json_decode($body, true);
            $response = array();
            $coin_data = array();
            $db_coins = array();
            $coinid_list = array();
            if (isset($coins['data']) && $coins['data'] != "" && is_array($coins['data'])) {
                ccpwp_track_coingecko_api_hit();
                foreach ($coins['data'] as $coin) {
                    // if (ccpwp_coin_array($coin['id'])) {
                    $coin_id = ccpwp_cmc_coin_array($coin['slug']);

                    $cp = ccpwp_set_default_if_empty($coin['quote']['USD']['price'], 0.00);
                    $response['coin_id'] = $coin_id;
                    // $response['rank'] = $coin['rank'];
                    $response['name'] = $coin['name'];
                    $response['symbol'] = strtoupper($coin['symbol']);
                    $response['price'] = $cp;
                    $response['percent_change_24h'] = ccpwp_set_default_if_empty($coin['quote']['USD']['percent_change_24h']);
                    $response['percent_change_7d'] = ccpwp_set_default_if_empty($coin['quote']['USD']['percent_change_7d']);
                    $response['percent_change_30d'] = ccpwp_set_default_if_empty($coin['quote']['USD']['percent_change_30d']);
                    //$response['percent_change_1y'] = ccpwp_set_default_if_empty($coin['quote']['USD']['percent_change_90d']);
                    //  $response['high_24h'] = $cp*1.02;
                    //  $response['low_24h'] =$cp*0.98;
                    $response['market_cap'] = ccpwp_set_default_if_empty($coin['quote']['USD']['market_cap'], 0);
                    $response['total_volume'] = ccpwp_set_default_if_empty($coin['quote']['USD']['volume_24h']);
                    $response['circulating_supply'] = ccpwp_set_default_if_empty($coin['circulating_supply']);
                    //  $response['ath'] = ccpwp_set_default_if_empty($coin['quote']['USD']['ath_price'],0);
                    //   $response['ath_date'] = ccpwp_set_default_if_empty($coin['quote']['USD']['ath_date']);
                    $response['weekly_price_data'] = null;
                    $response['logo'] = null;
                    $extradata = array('cmc_id' => $coin['id'], 'rank' => $coin['cmc_rank']);
                    $response['extradata'] = maybe_serialize($extradata);
                    $response['last_updated'] = gmdate('Y-m-d h:i:s');
                    $db_coins[] = $coin_id;
                    $coin_data[] = $response;

                     // Save data in chunks of 50 to avoid memory issues
                     if (count($coin_data) >= 50) {
                        self::save_coin_data($coin_data);
                        $coin_data = array(); // Reset array for next chunk
                    }
                }
                // Save any remaining data that was not saved in the last chunk
                if (!empty($coin_data)) {
                    self::save_coin_data($coin_data);
                }
                
                if ($page == 1) {
                    update_option('ccpwp-available-coins', $db_coins, true);
                }
                // save all the coin id's udated through API by default
                //update_option( 'ccpw-default-coins', $default_coins , $coinid_list );
                set_transient($data_cache_name, date('H:s:i'), $coingecko_api_cache_time * MINUTE_IN_SECONDS);

            }

            // fetch other than 250 default coins
            if (false == $ua_refresh_time) {
                self::ccpwp_update_unavailable_coins_data_cmc($ua_coins_cache);
            }

        } // end of ccpwp_get_coin_gecko_data()

/*
|-----------------------------------------------------------
| Fetching data through CoinGecko API and save in database
|-----------------------------------------------------------
 */
        public static function ccpwp_update_unavailable_coins_data($coin_ids = array())
        {

            $ua_coins_name = self::CCPWP_UNAVILABLE_DATA;
            $ua_refresh_time = self::CCPWP_REFRESH_COINS;
            $ua_coins_cache = get_option($ua_coins_name);
            $api_option = get_option("openexchange-api-settings");
            $coingecko_api_key = self::get_coingecko_api_key();
           // $coingecko_api_key = (isset($api_option['coingecko_api'])) ? $api_option['coingecko_api'] : "";
            $coingecko_api_cache_time = isset($api_option['select_cache_time']) ? (int) $api_option['select_cache_time'] : 10;

            //checks new or old user
            // Do not proceed further if
            if (!ccpwp_check_user()) {
                return;
            }

            if (is_array($coin_ids) && empty($coin_ids) || $coin_ids == '') {
                return false; // terminate further exectuition if no ids has passed in the argument;
            }
            $coin_ids_arr = $coin_ids;
            $required_coins = urlencode(implode(',', $coin_ids));
            $coins = array();
            $api_url = ccpwp_get_api_end_point() . 'coins/markets?ids=' . $required_coins . '&vs_currency=usd&order=market_cap_desc&sparkline=true&price_change_percentage=24h%2C7d%2C30d%2C1y&' . ccpwp_get_api_key_end_point() . '=' . $coingecko_api_key;
            //$api_url = 'https://api.coingecko.com/api/v3/coins/markets?ids='.$required_coins.'&vs_currency=usd&order=market_cap_desc&sparkline=true&price_change_percentage=24h%2C7d%2C30d%2C1y';
            $request = wp_remote_get($api_url, array('timeout' => 300, 'sslverify' => true));
            if (is_wp_error($request)) {
                return false; // Bail early
            }

            $body = wp_remote_retrieve_body($request);
            $coins = json_decode($body);

            if (ccpwp_check_api_errors($coins)) {

                return self::ccpwp_update_unavailable_coins_data_backup($coin_ids_arr);
            }
            $response = array();
            $coin_data = array();
            $db_coins = array();

            if (isset($coins) && $coins != "" && is_array($coins)) {
                ccpwp_track_coingecko_api_hit();
                foreach ($coins as $coin) {
                    $response['coin_id'] = $coin->id;
                    //$response['rank'] = $coin->market_cap_rank;
                    $response['name'] = $coin->name;
                    $response['symbol'] = strtoupper($coin->symbol);
                    $response['price'] = ccpwp_set_default_if_empty($coin->current_price, 0.00);
                    $response['percent_change_24h'] = ccpwp_set_default_if_empty($coin->price_change_percentage_24h, 0);
                    $response['market_cap'] = ccpwp_set_default_if_empty($coin->market_cap, 0);
                    $response['total_volume'] = ccpwp_set_default_if_empty($coin->total_volume);
                    $response['circulating_supply'] = ccpwp_set_default_if_empty($coin->circulating_supply);

                    $charts = array();
                    if (!empty($coin->sparkline_in_7d->price)) {
                        $x = 0;
                        foreach ($coin->sparkline_in_7d->price as $chart) {
                            if ($x % 6 === 0) {
                                if ($chart > 0.50) {
                                    $charts[] = number_format((float) $chart, 4, '.', '');
                                } else {
                                    $charts[] = number_format((float) $chart, 6, '.', '');
                                }
                            }
                            $x++;
                        }
                    }
                    $response['weekly_price_data'] = !empty($charts) ? serialize($charts) : null;

                    $response['logo'] = substr($coin->image, strpos($coin->image, "images") + 7);
                    $coin_data[] = $response;
                    $db_coins[] = $coin->id;
                }
                $DB = new ccpwp_database();
                $DB->create_table();
                $DB->ccpw_insert($coin_data);
                if (is_array($db_coins) && !empty($db_coins)) {
                    $db_coins = $ua_coins_cache == '' ? $db_coins : array_merge($ua_coins_cache, $db_coins);
                    $db_coins = array_unique($db_coins);
                    update_option($ua_coins_name, $db_coins, true);
                    set_transient($ua_refresh_time, date('H:s:i'), $coingecko_api_cache_time * MINUTE_IN_SECONDS);
                }

            }

        } // end of ccpwp_update_unavailable_coins_data()

/*
|-----------------------------------------------------------
| Fetching data through CoinGecko API and save in database
|-----------------------------------------------------------
 */
        public static function ccpwp_update_unavailable_coins_data_backup($coin_ids = array())
        {

            $ua_coins_name = self::CCPWP_UNAVILABLE_DATA;
            $ua_refresh_time = self::CCPWP_REFRESH_COINS;
            $ua_coins_cache = get_option($ua_coins_name);
            if (!is_array($coin_ids) && empty($coin_ids) || $coin_ids == '') {
                return false; // terminate further exectuition if no ids has passed in the argument;
            }
            $coin_data = array();
            foreach ($coin_ids as $key => $coin_id) {
                if (!ccpwp_coin_array($coin_id, true)) {
                    return;
                }
                $required_coins = $coin_id;
                $api_option = get_option("openexchange-api-settings");
                $coingecko_api_cache_time = isset($api_option['select_cache_time']) ? (int) $api_option['select_cache_time'] : 10;
                $coin = array();
                $request = wp_remote_get($api_url = self::COINPAPRIKA_API_ENDPOINT . 'tickers/' . ccpwp_coin_array($required_coins, true), array('timeout' => 300, 'sslverify' => true));
                if (is_wp_error($request)) {
                    return false; // Bail early
                }

                $body = wp_remote_retrieve_body($request);
                $coin = json_decode($body, true);

                $response = array();

                $db_coins = array();
                $coinid_list = array();
                if (isset($coin) && $coin != "" && is_array($coin)) {

                    $cp = ccpwp_set_default_if_empty($coin['quotes']['USD']['price'], 0.00);
                    $response['coin_id'] = ccpwp_coin_array($coin['id']);
                    // $response['rank'] = $coin['rank'];
                    $response['name'] = $coin['name'];
                    $response['symbol'] = strtoupper($coin['symbol']);
                    $response['price'] = $cp;
                    $response['percent_change_24h'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_change_24h']);
                    $response['percent_change_7d'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_change_7d']);
                    $response['percent_change_30d'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_change_30d']);
                    $response['percent_change_1y'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_change_1y']);
                    // $response['high_24h'] = $cp*1.02;;
                    // $response['low_24h'] =$cp*0.98;
                    $response['market_cap'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['market_cap'], 0);
                    $response['total_volume'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['volume_24h']);
                    $response['circulating_supply'] = ccpwp_set_default_if_empty($coin['circulating_supply']);

                    // $response['ath'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['ath_price'],0);
                    // $response['ath_date'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['ath_date']);
                    // $response['ath_change_percentage'] = ccpwp_set_default_if_empty($coin['quotes']['USD']['percent_from_price_ath'],0);
                    $response['last_updated'] = gmdate('Y-m-d h:i:s');

                    $coin_data[] = $response;
                    $db_coins[] = ccpwp_coin_array($coin['id']);

                    $DB = new ccpwp_database();
                    // $DB->create_table();
                    $DB->ccpw_insert($coin_data);
                    if (is_array($db_coins) && !empty($db_coins)) {
                        $db_coins = $ua_coins_cache == '' ? $db_coins : array_merge($ua_coins_cache, $db_coins);
                        $db_coins = array_unique($db_coins);
                        update_option($ua_coins_name, $db_coins, true);
                        set_transient($ua_refresh_time, date('H:s:i'), $coingecko_api_cache_time * MINUTE_IN_SECONDS);
                    }

                }
            }

        } // end of ccpwp_update_unavailable_coins_data()

        /*
        |-----------------------------------------------------------
        | Fetching data through Coinmarketcap API and save in database
        |-----------------------------------------------------------
         */
        public static function ccpwp_update_unavailable_coins_data_cmc($coin_ids = array())
        {
            $api_option = get_option("openexchange-api-settings");
            $api_type = (isset($api_option['select_api'])) ? $api_option['select_api'] : "coingecko";

            $ua_coins_name = ($api_type == "both_coinmarketcap" || $api_type == "coinmarketcap") ? self::CCPWP_UNAVILABLE_DATA_CMC : self::CCPWP_UNAVILABLE_DATA;
            $ua_refresh_time = self::CCPWP_REFRESH_COINS;
            $ua_coins_cache = get_option($ua_coins_name);

            //checks new or old user
            // Do not proceed further if
            if (!ccpwp_check_user()) {
                return;
            }

            if (!is_array($coin_ids) && empty($coin_ids) || $coin_ids == '') {
                return false; // terminate further exectuition if no ids has passed in the argument;
            }
            $coin_ids_arr = $coin_ids;
            $required_coins = urlencode(implode(',', $coin_ids));

            $coingecko_api_cache_time = isset($api_option['select_cache_time']) ? (int) $api_option['select_cache_time'] : 10;
            $api_key = (isset($api_option['coinmarketcap_api']) && !empty($api_option['coinmarketcap_api'])) ? $api_option['coinmarketcap_api'] : '';

            $coin = array();
            $request = wp_remote_get(self::CCPWP_COINMARKETCAP_API_ENDPOINT . 'v2/cryptocurrency/quotes/latest?slug=' . $required_coins . '&CMC_PRO_API_KEY=' . $api_key, array('timeout' => 120, 'sslverify' => true));
            if (is_wp_error($request)) {
                return false; // Bail early
            }

            $body = wp_remote_retrieve_body($request);
            $coins = json_decode($body, true);

            $response = array();

            $db_coins = array();
            $coinid_list = array();

            if (isset($coins['data']) && $coins['data'] != "" && is_array($coins['data'])) {
                ccpwp_track_coingecko_api_hit();

                foreach ($coins['data'] as $coin) {
                    $coin_id = ccpwp_cmc_coin_array($coin['slug']);
                    $cp = ccpwp_set_default_if_empty($coin['quote']['USD']['price'], 0.00);
                    $response['coin_id'] = $coin_id;
                    // $response['rank'] = $coin['rank'];
                    $response['name'] = $coin['name'];
                    $response['symbol'] = strtoupper($coin['symbol']);
                    $response['price'] = $cp;
                    $response['percent_change_24h'] = ccpwp_set_default_if_empty($coin['quote']['USD']['percent_change_24h']);
                    $response['percent_change_7d'] = ccpwp_set_default_if_empty($coin['quote']['USD']['percent_change_7d']);
                    $response['percent_change_30d'] = ccpwp_set_default_if_empty($coin['quote']['USD']['percent_change_30d']);
                    //$response['percent_change_1y'] = ccpwp_set_default_if_empty($coin['quote']['USD']['percent_change_90d']);
                    //  $response['high_24h'] = $cp*1.02;
                    //  $response['low_24h'] =$cp*0.98;
                    $response['market_cap'] = ccpwp_set_default_if_empty($coin['quote']['USD']['market_cap'], 0);
                    $response['total_volume'] = ccpwp_set_default_if_empty($coin['quote']['USD']['volume_24h']);
                    $response['circulating_supply'] = ccpwp_set_default_if_empty($coin['circulating_supply']);
                    //  $response['ath'] = ccpwp_set_default_if_empty($coin['quote']['USD']['ath_price'],0);
                    //   $response['ath_date'] = ccpwp_set_default_if_empty($coin['quote']['USD']['ath_date']);
                    $response['weekly_price_data'] = null;
                    $response['logo'] = null;
                    $extradata = array('cmc_id' => $coin['id'], 'rank' => $coin['cmc_rank']);
                    $response['extradata'] = maybe_serialize($extradata);
                    $response['last_updated'] = gmdate('Y-m-d h:i:s');
                    $db_coins[] = $coin['slug'];
                    $coin_data[] = $response;
                }

                $DB = new ccpwp_database();
                // $DB->create_table();
                $DB->ccpw_insert($coin_data);
                if (is_array($db_coins) && !empty($db_coins)) {
                    $db_coins = $ua_coins_cache == '' ? $db_coins : array_merge($ua_coins_cache, $db_coins);
                    $db_coins = array_unique($db_coins);
                    update_option($ua_coins_name, $db_coins, true);
                    set_transient($ua_refresh_time, date('H:s:i'), $coingecko_api_cache_time * MINUTE_IN_SECONDS);
                }

            }

        } // end of ccpwp_update_unavailable_coins_data()

        /*
        Historical data for a given coin
         */

        public static function ccpw_coin_historical_data($coin_id)
        {
            $api_option = get_option("openexchange-api-settings");
          //  $coingecko_api_key = (isset($api_option['coingecko_api'])) ? $api_option['coingecko_api'] : "";
            $coingecko_api_key = self::get_coingecko_api_key();
            $coingecko_api_cache_time = isset($api_option['select_cache_time']) ? (int) $api_option['select_cache_time'] : 10;

            //checks old or new user
            // Do not proceed further if

            if (!ccpwp_check_user()) {
                return;
            }

            $historical_coin_list = get_transient(self::CCPWP_HISTORICAL_DATA . $coin_id);
            $historical_c_list = array();
            if (empty($historical_coin_list) || $historical_coin_list === "") {
                // $request = wp_remote_get('http://coincap.io/history/365day/' . $coin_id, array('timeout' => 120));
                $api_url = ccpwp_get_api_end_point() . 'coins/' . $coin_id . '/market_chart?vs_currency=usd&days=365&' . ccpwp_get_api_key_end_point() . '=' . $coingecko_api_key;
                $request = wp_remote_get($api_url, array('timeout' => 120, 'sslverify' => true));
                if (is_wp_error($request)) {
                    return false; // Bail early
                }

                $body = wp_remote_retrieve_body($request);
                $historical_coinsdata = json_decode($body);
                if (ccpwp_check_api_errors($historical_coinsdata)) {
                    return self::ccpw_coin_historical_data_backup($coin_id);
                }
                if (!empty($historical_coinsdata)) {
                    ccpwp_track_coingecko_api_hit();
                    set_transient(self::CCPWP_HISTORICAL_DATA . $coin_id, $historical_coinsdata, self::HISTORICAL_DATA_TIME);
                    $historical_coin_list = $historical_coinsdata;

                }

            }
            if (!empty($historical_coin_list)) {
                return $historical_coin_list;
            }
        }

        /*
        |--------------------------------------------------------------------------
        | Backupt API to fetch historical data
        |--------------------------------------------------------------------------
         */
        public static function ccpw_coin_historical_data_backup($coin_id)
        {

            $interval = "1d";

            $days = date('Y-m-d', strtotime('-364 day'));

            $historical_coin_list = get_transient(self::CCPWP_HISTORICAL_DATA . $coin_id);
            $historical_c_list = array();
            if (false == $historical_coin_list || $historical_coin_list === "") {
                $api_url = self::COINPAPRIKA_API_ENDPOINT . 'tickers/' . ccpwp_coin_array($coin_id, true) . '/historical?start=' . $days . '&interval=' . $interval;
                $request = wp_remote_get($api_url, array('timeout' => 120, 'sslverify' => true));
                if (is_wp_error($request)) {
                    return false; // Bail early
                }

                $body = wp_remote_retrieve_body($request);
                $historical_coinsdata = json_decode($body, true);
                $customarray = [];
                if (is_array($historical_coinsdata)) {
                    foreach ($historical_coinsdata as $key => $value) {
                        $customarray['prices'][] = array(0 => strtotime($value['timestamp']) * 1000, 1 => $value['price']);
                        $customarray['market_caps'][] = array(0 => strtotime($value['timestamp']) * 1000, 1 => $value['market_cap']);
                        $customarray['total_volumes'][] = array(0 => strtotime($value['timestamp']) * 1000, 1 => $value['volume_24h']);

                    }
                }

                if (!empty($historical_coinsdata->error)) {
                    return;
                }

                if (isset($customarray)) {
                    set_transient(self::CCPWP_HISTORICAL_DATA . $coin_id, $historical_coinsdata, self::HISTORICAL_DATA_TIME);
                    $historical_coin_list = (object) $customarray;

                }
                if (!empty($historical_coin_list)) {
                    return $historical_coin_list;
                }
            }
        }
        public static function ccpwp_historical_coins_from_cmc_api($coin_id)
        {

            $interval = "1d";
            $startTime = date('Y-m-d', strtotime('-364 day'));
            $endTime = date('Y-m-d', strtotime('now'));

            $historical_coin_list = get_transient(self::CCPWP_HISTORICAL_DATA . $coin_id);
            $DB = new ccpwp_database();
            $coin_ex_data = !empty($coin_id) ? $DB->get_coin_logo($coin_id) : "";
            $api_option = get_option("openexchange-api-settings");
            $api_key = (isset($api_option['coinmarketcap_api']) && !empty($api_option['coinmarketcap_api'])) ? $api_option['coinmarketcap_api'] : '';

            if (isset($coin_ex_data['extradata']) && !empty($coin_ex_data['extradata'])) {
                $decode = maybe_unserialize($coin_ex_data['extradata']);

                $historical_c_list = array();
                if (false == $historical_coin_list || $historical_coin_list === "") {
                    $api_url = self::CCPWP_COINMARKETCAP_API_ENDPOINT . "v2/cryptocurrency/quotes/historical?CMC_PRO_API_KEY=$api_key&interval=$interval&time_start=$startTime&time_end=$endTime&id=" . $decode['cmc_id'];
                    $request = wp_remote_get($api_url, array('timeout' => 120, 'sslverify' => true));
                    if (is_wp_error($request)) {
                        return false; // Bail early
                    }

                    $body = wp_remote_retrieve_body($request);
                    $historical_coinsdata = json_decode($body, true);
                    if (isset($historical_coinsdata['status']['error_code']) && $historical_coinsdata['status']['error_code'] == 1006) {
                        return self::ccpw_coin_historical_data($coin_id);
                    }

                    $customarray = [];
                    if (is_array($historical_coinsdata['data'])) {
                        // foreach ($historical_coinsdata['data'] as $first) {
                        foreach ($historical_coinsdata['data']['quotes'] as $key => $value) {
                            $customarray['prices'][] = array(0 => strtotime($value['timestamp']) * 1000, 1 => $value['quote']['USD']['price']);
                            $customarray['market_caps'][] = array(0 => strtotime($value['timestamp']) * 1000, 1 => $value['quote']['USD']['market_cap']);
                            $customarray['total_volumes'][] = array(0 => strtotime($value['timestamp']) * 1000, 1 => $value['quote']['USD']['volume_24h']);

                        }
                        //}
                    }

                    if (!empty($historical_coinsdata->error)) {
                        return;
                    }

                    if (isset($customarray)) {
                        ccpwp_track_coingecko_api_hit();
                        set_transient(self::CCPWP_HISTORICAL_DATA . $coin_id, $historical_coinsdata, self::HISTORICAL_DATA_TIME);
                        return (object) $customarray;

                    }
                }
            }

        }

        public static function ccpw_coin_period_historical($coin_id, $period)
        {
            $DB = new ccpwp_database();
            $cache = 'ccpw-chart-cache-' . $coin_id . '-' . $period;
            $limit = 28;
            $aggre = 6;
            $coin_data = array();
            if ($period == "7d") {
                $limit = 28;
                $aggre = 6;
                if (get_transient($cache)) {
                    $coin_data = $DB->get_coin_weekly_data($coin_id);
                }
            } else {
                $limit = 24;
                $aggre = 1;
                if (get_transient($cache)) {
                    $coin_data = $DB->get_coin_extra_info_data($coin_id);
                }
            }
            $historical_c_list = array();

            if ((empty($coin_data) || $coin_data == "")) {

                // create a table and gather all data in case the table is removed somehow
                // if (false === $DB->is_table_exists()) {
                //     //$api_obj = new CCPWP_api_data();
                //     CCPWP_api_data::ccpwp_get_api_data();
                // }
                $api_option = get_option("openexchange-api-settings");
                //$coingecko_api_key = (isset($api_option['coingecko_api'])) ? $api_option['coingecko_api'] : "";
                $coingecko_api_key = self::get_coingecko_api_key();
                $api_url = ccpwp_get_api_end_point() . 'coins/markets?vs_currency=usd&ids=' . $coin_id . '&order=market_cap_desc&per_page=1&page=1&sparkline=true&' . ccpwp_get_api_key_end_point() . '=' . $coingecko_api_key;
                $request = wp_remote_get($api_url, array('timeout' => 300, 'sslverify' => true));
                //$request = wp_remote_get('https://min-api.cryptocompare.com/data/histohour?fsym=' . $coin_symbol . '&tsym=USD&limit='. $limit. '&aggregate='.$aggre .'&e=CCCAGG', array('timeout' => 120));

                if (is_wp_error($request)) {
                    return false; // Bail early
                }

                $body = wp_remote_retrieve_body($request);
                $response = json_decode($body);
                foreach ($response as $coin) {
                    $charts = array();
                    if (!empty($coin->sparkline_in_7d->price)) {
                        $x = 0;
                        foreach ($coin->sparkline_in_7d->price as $chart) {
                            if ($x % 6 === 0) {
                                if ($chart > 0.50) {
                                    $charts[] = number_format((float) $chart, 4, '.', '');
                                } else {
                                    $charts[] = number_format((float) $chart, 6, '.', '');
                                }
                            }
                            $x++;
                        }
                    }
                    $coin_data = !empty($charts) ? serialize($charts) : null;

                }

                // Make sure coin_data is a non-emtpy
                if (!empty($coin_data)) {
                    ccpwp_track_coingecko_api_hit();
                    $DB->ccpw_insert_coin_weekly_data($coin_id, $coin_data);
                    set_transient($cache, 'available', 3 * HOUR_IN_SECONDS);
                    $coin_data = $DB->get_coin_weekly_data($coin_id);
                }
            }

            if (!empty($coin_data)) {
                return $coin_data;
            }
        }


         /**
         * Save coin data to the database.
         *
         * @param array $coin_data The coin data to save.
         */
        private static function save_coin_data($coin_data)
        {
            $DB = new ccpwp_database();
            $DB->ccpw_insert($coin_data);
        }

         /**
         * Check if a string contains emoji.
         *
         * @param string $string The string to check.
         * @return bool True if the string contains emoji, false otherwise.
         */
        public static function contains_emoji($string)
        {
            return preg_match('/[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}]/u', $string) > 0;
        }
        /* USD conversions */

        public static function ccpwp_usd_conversions($currency)
        {
            // use common transient between cmc and ccpw
            $conversions = get_transient(self::CCPWP_USD_CONVERSION);
            $conversions_option = get_option(self::CCPWP_USD_CONVERSION);
            if (empty($conversions) || $conversions === "" || empty($conversions_option)) {
                $api_option = get_option("openexchange-api-settings");
                $request = "";
                $api = (isset($api_option['openexchangerate_api'])) ? $api_option['openexchangerate_api'] : "";
                if (!empty($api)) {
                    $request = wp_remote_get(self::OPENEXCHANGERATE_API_ENDPOINT . $api . '', array('timeout' => 120, 'sslverify' => true));

                } else {
                    $conversions_option = array('USD' => 1);
                }
                if (is_wp_error($request)) {
                    return false;
                }

                $currency_ids = array("USD", "AUD", "BRL", "CAD", "CZK", "DKK", "EUR", "HKD", "HUF", "ILS", "INR", "JPY", "MYR", "MXN", "NOK", "NZD", "PHP", "PLN", "GBP", "SEK", "CHF", "TWD", "THB",
                    "TRY", "CNY", "KRW", "RUB", "SGD", "CLP", "IDR", "PKR", "ZAR", "NGN", "JMD");
                $body = wp_remote_retrieve_body($request);
                $conversion_data = json_decode($body);

                if (isset($conversion_data->rates)) {
                    $conversion_data = (array) $conversion_data->rates;
                } else {
                    $conversion_data = array();
                    if (!empty($conversions_option)) {
                        if ($currency == "all") {

                            return $conversions_option;

                        } else {
                            if (isset($conversions_option[$currency])) {
                                return $conversions_option[$currency];
                            }
                        }
                    }
                }

                if (is_array($conversion_data) && count($conversion_data) > 0) {
                    $conversions_option = [];
                    foreach ($conversion_data as $key => $currency_price) {
                        if (in_array($key, $currency_ids)) {
                            $conversions_option[$key] = $currency_price;
                        }
                    }

                    uksort($conversions_option, function ($key1, $key2) use ($currency_ids) {
                        return (array_search($key1, $currency_ids) > array_search($key2, $currency_ids)) ? 1 : -1;
                    });
                    update_option(self::CCPWP_USD_CONVERSION, $conversions_option);
                    set_transient(self::CCPWP_USD_CONVERSION, $conversions_option, self::USD_CONVERSION_TIME);
                }
            }

            if ($currency == "all") {

                return $conversions_option;

            } else {
                if (isset($conversions_option[$currency])) {
                    return $conversions_option[$currency];
                }
            }
        }

    }
}
