<?php
/**
 * Google Client admin class.  
 *
 * Handles retrieving whether a particular notice has been dismissed or not,
 * as well as marking a notice as dismissed.
 *
 * @since 6.0.0
 *
 * @package MonsterInsights
 * @subpackage GA Client
 * @author  Chris Christoff
 */

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

final class MonsterInsights_GA {

	/**
	 * Holds the GA client object if using oAuth.
	 *
	 * @access public
	 * @since 6.0.0
	 * @var MonsterInsights_GA_Client $client GA client object.
	 */
	public $client;

	/**
	 * Google Profile ID.
	 *
	 * @access public
	 * @since 6.0.0
	 * @var int $profile ID of profile in use.
	 */
	public $profile;

	/**
	 * Google UA code.
	 *
	 * @access public
	 * @since 6.0.0
	 * @var string|false $ua Google UA code for the current profile if valid oAuth in use, else false.
	 */
	public $ua;

	/**
	 * Google profile name.
	 *
	 * @access public
	 * @since 6.0.0
	 * @var string|false $ua Google profile name for the current profile if valid oAuth in use, else false.
	 */
	public $name;

	/**
	 * Status of Google client object.
	 *
	 * @access public
	 * @since 6.0.0
	 * @var string $status Possible values include manual, expired, valid, needs-permissions, blocked and none.
	 */
	public $status;

	/**
	 * oAuth Permissions Version.
	 *
	 * @access public
	 * @since 6.0.0
	 * @var string $oauth_version Version of oAuth permissions granted.
	 */
	public $oauth_version;	

	/**
	 * Holds the base object.
	 *
	 * @access public
	 * @since 6.0.0
	 * @var MonsterInsights $base MonsterInsights Base object.
	 */
	public $base;

	/**
	 * Primary class constructor.
	 *
	 * @access public
	 * @since 6.0.0
	 */
	public function __construct() {
		// Get object 
		$this->client        = $this->get_client();
		$this->profile       = $this->get_profile();
		$this->ua            = $this->get_ua();
		$this->name          = $this->get_name();
		$this->oauth_version = $this->get_oauth_version();
		$this->status        = $this->get_status();
		$this->base 		 = MonsterInsights();


		// Show any info/error notices
		$this->get_notices();

		// Authentication Actions
		add_action( 'wp_ajax_monsterinsights_google_view',  array( $this, 'google_auth_view' ) );
		add_action( 'wp_ajax_monsterinsights_google_cancel',  array( $this, 'google_cancel' ) );

		add_action( 'admin_init', array( $this, 'deactivate_google' ) ); // Deactivate
	}

	private function get_client() {
		return ! empty( $this->client ) ? $this->client : monsterinsights_create_client();
	}

	private function set_test_client() { 
		$this->client = monsterinsights_create_test_client();
	}

	private function set_client() { 
		$this->client = monsterinsights_create_client();
	}

	/**
	 * Get the current GA profile
	 *
	 * @return null
	 */
	private function get_profile() {
		return monsterinsights_get_option( 'analytics_profile', false );
	}

	private function get_name() {
		return monsterinsights_get_option( 'analytics_profile_name', false );
	}

	private function get_ua() {
		return monsterinsights_get_ua();
	}

	private function get_oauth_version() {
		return monsterinsights_get_option( 'oauth_version', '1.0' );
	}

	private function get_status() {
		$status = 'valid';
		if ( ! empty( $this->profile ) ) {
			// We are using oAuth
			
			$last_run = monsterinsights_get_option( 'cron_last_run', false );
			$failed   = monsterinsights_get_option( 'cron_failed', false );
			$dash_dis = monsterinsights_get_option( 'dashboards_disabled', false );

			// See if issue connecting or expired
			if ( ! $dash_dis && $failed && ( $last_run === false || monsterinsights_hours_between( $last_run ) >= 48 )  ) { 
				$status = 'blocked';
			}

			$access_token = $this->client->get_access_token();

			// Check to make sure access token is there and not expired
			if ( empty( $access_token ) || empty( $access_token['expires'] ) || current_time( 'timestamp' ) >= $access_token['expires'] ) {
				$status = 'expired';
				return $status;
			}

			// See if needs permissions
			if ( version_compare( $this->oauth_version, '1.0', '<' ) ) { 
				$status = 'needs-permissions';
			}
			
		} else if ( ! empty( $this->ua ) ) {
			// We are using manual
			
		} else {
			// We do not have oAuth or manual active
			$status = 'empty';
		}

		return $status;
	}

	private function get_notices() {
		// Notice for no manual or profile GA
		if ( $this->status === 'empty' ) {
			add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_empty_notice' ),6 );
		}

		$current_page = filter_input( INPUT_GET, 'page' );

		// Only show expired, needs permission, or blocked notices on the MI pages
		// We do this because unlike status empty, these only block reporting, not the frontend
		// tracking from working, and as a result, these are not as urgent. Plus users generally
		// don't like global notices.
		if ( strpos( $current_page, 'monsterinsights' ) === 0 ) {
		
			// Notice for GA Access token expired (needs re-authenticate)
			if ( $this->status === 'expired' ) {
				add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_expired_notice' ),6 );
			}
			
			// Notice for Needs Permissions
			if ( $this->status === 'needs-permissions' ) {
				add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_needs_permissions_notice' ),6 );
			}

			// Notice for trouble connecting to Google
			if ( $this->status === 'blocked' ) {
				add_action( 'admin_notices', array( $this, 'monsterinsights_show_admin_config_blocked_notice' ),6 );
			}
		}
	}

	/**
	 * Used when switching GA profiles, or switching
	 * to/from oAuth <--> manual, or when reauthenticating
	 * or deleting GA profile.
	 *
	 * @return null
	 */
	private function reinitialize() { 
		// Get object 
		$this->client        = $this->get_client();
		$this->profile       = $this->get_profile();
		$this->ua            = $this->get_ua();
		$this->name          = $this->get_name();
		$this->oauth_version = $this->get_oauth_version();
		$this->status        = $this->get_status();

		// Re-get data if possible
		if ( $this->ua === 'valid' ) {
			$this->refresh_dashboard_data();
		}
	}

	public function create_auth_url() {
		return $this->client->createAuthUrl();
	}

	/**
	 * Getting the analytics profiles
	 *
	 * Doing the request to the Google analytics API and if there is a response, parses this response and return its
	 * array
	 *
	 * @return array
	 */
	public function get_profiles() { // @todo: this needs exception handling for a 401 login required		
		$accounts = $this->get_profiles_request();
		if ( is_array( $accounts ) ) {
			return $accounts;
		} else {
			return array();
		}
	}

	public function find_selected_profile( $profile_id ) {
		$profiles = $this->get_profiles();
		$found  = array();
		foreach ( $profiles as $account ) {
			foreach ( $account['items'] as $profile ) {
				foreach ( $profile['items'] as $subprofile ) {
					if ( isset( $subprofile['id'] ) && $subprofile['id'] == $profile_id ) {
						$found = array(
							'id'   => $profile_id,
							'ua'   => $subprofile['ua_code'],
							'name' => $subprofile['name'],

						);
						break 3;
					}
				}
			}
		}
		return $found;
	}

	public function save_selected_profile( $profile ) {
		monsterinsights_update_option( 'analytics_profile', $profile['id'] );
		monsterinsights_update_option( 'analytics_profile_code', $profile['ua'] );
		monsterinsights_update_option( 'analytics_profile_name', $profile['name'] );
		monsterinsights_set_client_oauth_version();
	}


	/**
	 * Get accounts request
	 *
	 * @param array $response
	 *
	 * @return mixed
	 */
	private function get_profiles_request() {
		global $wp_version;
		$version = str_replace( '-src', '', $wp_version );
		$accounts    = array();
		$start_index = 1;
		$paginate    = false;
		$continue    = true;
		while ( $continue ) {
			$body     = array(
				'max-results'  => 1000,
				'start-index'  => $paginate ? $start_index + 1000 : $start_index,
			);
			if ( $paginate ) {
				$start_index = $start_index + 1000;
			}
			$response = $this->client->do_request( 'https://www.googleapis.com/analytics/v3/management/accounts/~all/webproperties/~all/profiles', false, 'GET', $body );
			if ( ! empty( $response ) ) {
				$response = array(
					'response' => array( 'code' => $this->client->get_http_response_code() ),
					'body'     => json_decode( $response->getResponseBody(), true ),
				);
			} else {
				if ( version_compare( $version, '4.6', '<' ) ) {
					return esc_html__( 'MonsterInsights requires WordPress version 4.6 or newer to use oAuth. Please update your WordPress version.', 'google-analytics-for-wordpress' );
				} else {
					if ( ! empty( $accounts ) ) {
						return $accounts;
					} else {
						return esc_html__( 'Google Analytics had a connection error or your Google account is not signed up for Google Analytics.', 'google-analytics-for-wordpress' );
					}
				}
			}
			
			if ( isset( $response['response']['code'] ) && $response['response']['code'] == 200 ) {
				if ( ! empty( $response['body']['items'] ) && is_array( $response['body']['items'] ) ) {
					foreach ( $response['body']['items'] as $item ) {

						// Only deal with web properties, not apps.
						if ( isset( $item['type'] ) && 'WEB' != $item['type'] ) {
							continue;
						}

						/**
						 * Future:
						* // Accounts
						* 	// Properties
						* 		// Views
						* $items = array(
						* 	{account_id} => array(
						* 		{property_id} => array(
						* 			{view_id} => array( 
						* 				'account_id'  => '',
						* 				'property_id' => '',
						* 				'view_id'	  => '',
						* 				'url'		  => '',
						* 				'view_name'	  => '',
						* 				'ua_code'	  => '',
						* 			),
						* 		),
						* 	),
						* ),
						**/
						/*
						CurrenT:
						$accounts[ $item['accountId'] ] = array( 
							'id'          => $item['accountId'],
							'ua_code'     => $item['webPropertyId'],
							'parent_name' => $item['websiteUrl'],
							'items'       => array(
								[ $item['internalWebPropertyId'] ]= array( 
									'id'          => $item['webPropertyId'],
									'name'        => $item['websiteUrl'],
									'items'       => array(
										[ $item['id'] ] = array( 
											'name'    => $item['name'] . ' (' . $item['webPropertyId'] . ')',
											'ua_code' => $item['webPropertyId'],
											'id'      => $item['id'],
										);
									),
								);
							),
						);
						*/


						if ( empty( $accounts[ $item['accountId'] ] ) ) {
							$accounts[ $item['accountId'] ] = array( 
								'id'          => $item['accountId'],
								'ua_code'     => $item['webPropertyId'],
								'parent_name' => $item['websiteUrl'],
								'items'       => array(),
							);
						}

						if ( empty( $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ] ) ) {
							$accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ]= array( 
								'id'          => $item['webPropertyId'],
								'name'        => $item['websiteUrl'],
								'items'       => array(),
							);
						}

						if ( empty( $accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ]['items'][ $item['id'] ] ) ) {
							$accounts[ $item['accountId'] ]['items'][ $item['internalWebPropertyId'] ]['items'][ $item['id'] ] = array( 
								'name'    => $item['name'] . ' (' . $item['webPropertyId'] . ')',
								'ua_code' => $item['webPropertyId'],
								'id'      => $item['id'],
							);
						}
					}
				}
			} else if ( isset( $response['response']['code'] ) && $response['response']['code'] !== 200 && ! $paginate ) {
				if ( version_compare( $version, '4.6', '<' ) ) {
					return esc_html__( 'MonsterInsights requires WordPress version 4.6 or newer to use oAuth. Please update your WordPress version.', 'google-analytics-for-wordpress' );
				} else {
					if ( ! empty( $accounts ) ) {
						return $accounts;
					} else {
						$code = isset( $response['response']['code'] ) ? $response['response']['code'] : 'Unknown';
						$type = isset( $response['body']['error']['errors'][0]['reason'] ) ? $response['body']['error']['errors'][0]['reason'] : false;
						if ( $type === 'insufficientPermissions' ) {
							return esc_html__( 'Please ensure your Google Account is signed up for Google Analytics.', 'google-analytics-for-wordpress' );
						} else if ( $type === 'badRequest' ) {
							return esc_html__( 'Bad Request. Please contact support.', 'google-analytics-for-wordpress' );
						} else if ( $type === 'dailyLimitExceeded' ) {
							return esc_html__( 'Daily Limit Exceeded. Please contact support.', 'google-analytics-for-wordpress' );
						} else if ( $type === 'userRateLimitExceeded' ) {
							return esc_html__( 'User Rate Limit Exceeded. Wait 2 minutes and then try again.', 'google-analytics-for-wordpress' );
						} else if ( $type === 'rateLimitExceeded' ) {
							return esc_html__( 'Project Rate Limit Exceeded. Wait 2 minutes and then try again.', 'google-analytics-for-wordpress' );
						} else if ( $type === 'quotaExceeded' ) {
							return esc_html__( 'Project Rate Limit Quota Exceeded. Wait 2 minutes and then try again.', 'google-analytics-for-wordpress' );
						} else if ( $type === 'internalServerError' || $type === 'backendError' ) {
							return esc_html__( 'Google Analytics is having API issues on their side. Wait 2 minutes and then try again.', 'google-analytics-for-wordpress' );
						} else {
							return sprintf( esc_html__( 'Google Analytics had a connection error. Error code: %1$s. Reason: %2$s', 'google-analytics-for-wordpress' ), $code, $type );
						}
					}
				}
			}

			if ( isset( $response['body']['totalResults'] ) && $start_index < $response['body']['totalResults'] && ! empty( $response['body']['nextLink'] ) ) {
				$paginate    = true;
			} else {
				$continue    = false;
			}
		}
		return $accounts;
	}

	private function clear_oauth_data() {
		// Delete the stored profiles
		$options = array(
			'analytics_profile_code',
			'analytics_profile',
			'analytics_profile_name',
			'oauth_version',
			'cron_failed',
			'cron_last_run',
		);
		monsterinsights_delete_options( $options );

		// Destroy the data
		$this->base->reports->delete_aggregate_data();
		
		$this->client->clear_data();
	}

	private function clear_manual_data() {
		// Delete the manual ua code
		monsterinsights_delete_option( 'manual_ua_code' );
	}

	public function deactivate_google() {
		// Check if user pressed the deactivate button and nonce is valid
		if ( ! isset( $_POST['monsterinsights-google-deauthenticate-submit'] ) ) {
			return;
		}

		if ( ! wp_verify_nonce( $_POST['monsterinsights-google-authenticated-nonce'], 'monsterinsights-google-authenticated-nonce' ) ) {
			return;
		}

		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
			return;
		}

		// Destroy the client
		$this->clear_oauth_data();

		// Refresh the client
		$this->reinitialize();
	}

	public function refresh_dashboard_data( ) {
		// Destroy the data
		$this->base->reports->delete_aggregate_data();
		
		$this->base->reports->run_cron();
	}

	/**
	 * Check if client has a refresh token
	 * @return bool
	 */
	public function has_refresh_token() {
		return $this->client->is_authenticated();
	}

	/**
	 * Doing request to Google Analytics
	 *
	 * This method will do a request to google and get the response code and body from content
	 *
	 * @param string $target_request_url
	 *
	 * @return array|null
	 */
	public function do_request( $target_request_url ) {
		$response = $this->client->do_request( $target_request_url );
		if ( ! empty( $response ) ) {
			return array(
				'response' => array( 'code' => $this->client->get_http_response_code() ),
				'body'     => json_decode( $response->getResponseBody(), true ),
			);
		}
	}
	
	/**
	 * Wrapper for authenticate the client. If authentication code is send it will get and check an access token.
	 *
	 * @param mixed $authentication_code
	 *
	 * @return boolean
	 */
	public function authenticate( $authentication_code = null ) {
		// When authentication again we should clean up some stuff
		monsterinsights_delete_options( array( 'cron_last_run', 'cron_failed' ) );
		return $this->client->authenticate_client( $authentication_code );
	}

	public function google_auth_view() {
		$view   = isset( $_POST['view'] ) && in_array( $_POST['view'], array( 'prestart', 'start', 'enterkey', 'selectprofile', 'done' ) ) ? $_POST['view'] : '';
		$reauth = isset( $_POST['reauth'] ) && $_POST['reauth'] && $_POST['reauth'] !== 'false'  ? true : false;

		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
			echo esc_html__( 'Permission Denied', 'google-analytics-for-wordpress');
			wp_die();
		}

		// We run the save routines, if required, for a view, and then after that send back the results + next view
		$nextview = array();

		switch ( $view ) {
			case 'start':
				if ( ! $this->is_wp_blocking_google() && ! $this->is_google_on_blacklist() ) {
					$auth_url = $this->create_auth_url();
					$nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url );
				} else {
					$error    = esc_html__( 'Cannot connect to Google', 'google-analytics-for-wordpress' );
					$nextview = monsterinsights_google_auth_error_view( $reauth, $error );
				}
				break;

			case 'enterkey':
				$auth_key = ! empty( $_POST['stepdata'] ) ? sanitize_text_field( $_POST['stepdata'] ) : '';
				if ( $auth_key ) {
					if ( $this->test_authkey( $auth_key ) ) {
						$profiles = $this->get_profiles_request();
						delete_option( 'monsterinsights_get_profiles' );
						update_option( 'monsterinsights_get_profiles', $profiles );
						if ( ! empty( $profiles ) && is_array( $profiles ) ) {
							$select = $this->ga_select( $profiles );
							$nextview = monsterinsights_google_auth_selectprofile_view( $reauth, $select );
						} else if ( ! empty( $profiles ) && is_string( $profiles ) ) {
							// Error from Google
							$auth_url = $this->create_auth_url();
							$this->client->clear_data();
							$this->set_test_client();
							$nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html( $profiles ) );
						} else {
							// No profiles or not enough permissions
							$auth_url = $this->create_auth_url();
							$this->client->clear_data();
							$this->set_test_client();
							$nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html__( 'No profiles viewable for that account. Please use another account.', 'google-analytics-for-wordpress' ) );
						}
					} else {
						// if bad authentication error message
						$auth_url = $this->create_auth_url();
						$this->client->clear_data();
						$this->set_test_client();
						$nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html__( 'Bad Google Code. Please try again.', 'google-analytics-for-wordpress' ) );
					}
				} else {
					$auth_url = $this->create_auth_url();
					$this->client->clear_data();
					$this->set_test_client();
					// if no auth key error message
					$nextview = monsterinsights_google_auth_enterkey_view( $reauth, $auth_url, esc_html__( 'Please paste in your Google code.', 'google-analytics-for-wordpress' ) );
				}
				break;

			case 'selectprofile':
				$profile = ! empty( $_POST['stepdata'] ) ? absint( sanitize_text_field( $_POST['stepdata'] ) ) : '';
				if ( ! empty( $profile ) ) {
					$this->set_test_client();
					$profile = $this->find_selected_profile( $profile );
					if ( ! empty( $profile ) ) {

						$this->clear_manual_data(); // Just in case we were manual, clear out UA

						$this->client->move_test_to_live();
						$this->save_selected_profile( $profile );
						$this->set_client();
						$this->reinitialize();

						// Refresh reporting data
						$this->base->reports->refresh_aggregate_data();

						$nextview = monsterinsights_google_auth_done_view( $reauth );
					} else {
						// Invalid profile selected
						$profiles = get_option( 'monsterinsights_get_profiles', array() );
						$select   = $this->ga_select( $profiles );
						$nextview = monsterinsights_google_auth_selectprofile_view( $reauth, $select, esc_html__( 'Invalid profile selected.', 'google-analytics-for-wordpress' ) );
					}
				} else { 
					// No profile selected
					$profiles = get_option( 'monsterinsights_get_profiles', array() );
					$select   = $this->ga_select( $profiles );
					$nextview = monsterinsights_google_auth_selectprofile_view( $reauth, $select, esc_html__( 'Please select a profile.', 'google-analytics-for-wordpress' ) );
				}
				break;

			case 'done':
				$nextview = monsterinsights_google_auth_done_view( $reauth );
				break;
				
			case 'prestart':
			default:
				 $nextview = monsterinsights_google_auth_start_view( $reauth );
				break;
		}
		echo $nextview;
		wp_die();
	}

	public function google_cancel() {
		$view   = isset( $_POST['view'] ) && in_array( $_POST['view'], array( 'prestart', 'start', 'enterkey', 'selectprofile', 'done' ) ) ? $_POST['view'] : '';
		$reauth = isset( $_POST['reauth'] ) && $_POST['reauth'] && $_POST['reauth'] !== 'false'  ? true : false;

		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
			echo esc_html__( 'Permission Denied', 'google-analytics-for-wordpress');
			wp_die();
		}

		// If we cancelled on enterkey or selectprofile, delete the temp access tokens and set client back to normal client
		if ( $view === 'enterkey' || $view === 'selectprofile' ) {
			$this->client->clear_data();
			delete_option( 'monsterinsights_get_profiles' );
			$this->set_client();
		}
	}

	private function test_authkey( $authkey ) {
		$this->set_test_client();
		$result = $this->authenticate( $authkey );
		return $result;
	}

	/**
	 * Generates the GA select box
	 *
	 * @return null|string
	 */
	private function ga_select( $profiles = array() ) {
		if ( empty( $profiles ) || ! is_array( $profiles ) ) { 
			$profiles = $this->get_profiles();
		}
		
		$optgroups = array();
		foreach ( $profiles as $key => $value ) {
			foreach ( $value['items'] as $subitem ) {
				if ( empty( $optgroups[ $subitem['name'] ]['items'] ) ) {
					$optgroups[ $subitem['name'] ]['items'] = $subitem['items'];
				} else {
					$optgroups[ $subitem['name'] ]['items'] = array_merge( $optgroups[ $subitem['name'] ]['items'], $subitem['items'] );
				}
			}
		}

		$values = $optgroups;
		$select = '';
		$select .= '<div class="monsterinsights_ga_form">';
		$select .= '<label for="monsterinsights_step_data" id="monsterinsights_select_ga_profile_label">' . esc_html__( 'Analytics profile', 'google-analytics-for-wordpress' ) . ':</label>';
		$select .= '<select data-placeholder="' . esc_attr__( 'Select a profile', 'google-analytics-for-wordpress' ) . '" name="monsterinsights_step_data" class="monsterinsights-select300 monsterinsights_select_ga_profile" id="monsterinsights_step_data" style="width:80%;margin-left:10%;margin-right:10%;background-color: #FFF;">';
		$select .= '<option></option>';

		if ( count( $values ) >= 1 ) {
			foreach ( $values as $optgroup => $value ) {
				if ( ! empty( $value['items'] ) ) {
					$select .= $this->create_optgroup( $optgroup, $value );
				}
				else {
					$select .= '<option value="' . esc_attr( $value['id'] ) . '">' . esc_attr( stripslashes( $value['name'] ) ) . '</option>';
				}
			}
		}
		$select .= '</select>';
		$select .= '</div>';
		return $select;
	}

	/**
	 * Creates a optgroup with the items. If items contain items it will create a nested optgroup
	 *
	 * @param string $optgroup
	 * @param array  $value
	 * @param array  $select_value
	 *
	 * @return string
	 */
	private function create_optgroup( $optgroup, $value ) {
		$optgroup = '<optgroup label="' . esc_attr( $optgroup ) . '" disabled>';

		foreach ( $value['items'] as $option ) {
			if ( ! empty( $option['items'] ) ) {

				$optgroup .= $this->create_optgroup( esc_attr( $option['name'] ), $option );
			}
			else {
				$optgroup .= '<option value="' . esc_attr( $option['id'] ) . '">' . esc_attr( stripslashes( $option['name'] ) ) . '</option>';
			}
		}

		$optgroup .= '</optgroup>';

		return $optgroup;
	}

	/**
	 * See if Google is on the block_request list.
	 *
	 * @return bool 
	 */
	private function is_wp_blocking_google() {
		if ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) { // @todo: put this in sysinfo 
			if ( defined( 'WP_ACCESSIBLE_HOSTS' ) ) {
				$on_blacklist = $this->is_google_on_blacklist();
				if ( $on_blacklist ) {
					return true;
				} else {
					$params = array(
						'sslverify'     => false,
						'timeout'       => 60,
						'user-agent'    => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,
						'body'          => ''
					);
					$response = wp_remote_get( 'https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest', $params );
					if( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
						return false;
					} else {
						return true;
					}
				}
			} else {
				return true;
			}
		} else {
			$params = array(
				'sslverify'     => false,
				'timeout'       => 60,
				'user-agent'    => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,
				'body'          => ''
			);
			$response = wp_remote_get( 'https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest', $params );
			
			if( !is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
				return false;
			} else {
				return true;
			}
		}
	}

	/**
	 * See if Google is on the block_request list.
	 *
	 * @return bool 
	 */
	private function is_google_on_blacklist() { // @todo: put this in sysinfo
		$wp_http = new WP_Http();
		if ( $wp_http->block_request( 'https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest' ) ) {
			return true;
		}

		return false;
	}

	public function monsterinsights_show_admin_config_empty_notice() {
		$screen = get_current_screen(); 
		if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) !== false ) {
			return;
		}
		
		if ( ! defined( 'MONSTERINSIGHTS_SHOWING_EMPTY_CONFIG_NOTICE' ) ) {
			define( 'MONSTERINSIGHTS_SHOWING_EMPTY_CONFIG_NOTICE', true );
		}
		echo '<div class="error"><p>' . 
			sprintf( esc_html__( 'Please configure your %1$sGoogle Analytics settings%2$s!', 'google-analytics-for-wordpress' ),
				'<a href="' . admin_url( 'admin.php?page=monsterinsights_settings' ) . '">',
				'</a>'
			)
		. '</p></div>';
	}

	/**
	 * Throw a warning when the fetching failed
	 */
	public function monsterinsights_show_admin_config_expired_notice() {
		echo '<div class="error"><p>' . 
			sprintf(
				esc_html__( 'It seems the authentication for the plugin has expired or the connection to Google Analytics is blocked, please try %1$sre-authenticating%2$s with Google Analytics to allow the plugin to fetch data.', 'google-analytics-for-wordpress' ),
				'<a href="' . admin_url( 'admin.php?page=monsterinsights_settings' ) . '">',
				'</a>'
			)
		. '</p></div>';
	}

	/**
	 * Throw a warning when the fetching failed
	 */
	public function monsterinsights_show_admin_config_needs_permissions_notice() {
		echo '<div class="error"><p>' . 
			sprintf(
				esc_html__( 'It seems the authentication for the plugin is missing permissions. Please %1$sre-authenticate%2$s with Google Analytics to allow the plugin to fetch data.', 'google-analytics-for-wordpress' ),
				'<a href="' . admin_url( 'admin.php?page=monsterinsights_settings' ) . '">',
				'</a>'
			)
		. '</p></div>';
	}

	/**
	 * Throw a warning when the fetching failed
	 */
	public function monsterinsights_show_admin_config_blocked_notice() {
		echo '<div class="error"><p>' . 
			sprintf(
				esc_html__( 'Data is not up-to-date, there was an error in retrieving the data from Google Analytics. This error could be caused by several issues. If the error persists, please see %1$sthis page%2$s.', 'google-analytics-for-wordpress' ),
				'<a href="https://www.monsterinsights.com/docs/blocked-connection/">',
				'</a>'
			)
		. '</p></div>';
	}
}