<?php

class Breeze_Store_Files {

	var $store_files_dir    = '/breeze/';
	var $cdn_pixel_file_url = 'https://connect.facebook.net/en_US/fbevents.js';
	var $cdn_gtm_js_file    = 'https://www.googletagmanager.com/gtm.js';
	var $cdn_gtm_js_route   = 'https://www.googletagmanager.com/gtag/js';

	public function init( $html = 0, $options = array() ) {

		if ( empty( $options ) || ! $html ) {
			return $html;
		}

		$wp_upload       = wp_upload_dir();
		$store_files_uri = $wp_upload['baseurl'] . $this->store_files_dir;
		$store_files_dir = $wp_upload['basedir'] . $this->store_files_dir;

		if ( $options['breeze-store-googlefonts-locally'] ) {
			$html = $this->extract_google_fonts_css( $html, $store_files_dir, $store_files_uri );

		}

		if ( $options['breeze-store-googleanalytics-locally'] ) {
			$html = $this->extract_gtm( $html, $store_files_dir, $store_files_uri );
			$html = $this->extract_google_analytics( $html, $store_files_dir, $store_files_uri );
		}

		if ( $options['breeze-store-facebookpixel-locally'] ) {
			$html = $this->extract_facebook_pixel( $html, $store_files_dir, $store_files_uri );
		}

		return $html;
	}

	/**
	 * Get all google fonts css files
	 *
	 * @param $html
	 *
	 * @return mixed
	 */
	public function extract_google_fonts_css( $html, $files_dir, $stored_files_uri ) {

		// Preset routes
		$files_dir        = $files_dir . 'google/fonts/';
		$stored_files_uri = $stored_files_uri . 'google/fonts/';

		// Extract Google Fonts declarations using link tags
		$pattern = '/<link[^>]+?href=["\'](https:\/\/fonts\.googleapis\.com\/css[^"\']+)["\'][^>]+?>/i';
		preg_match_all( $pattern, $html, $matches );

		$font_declarations = $matches[1];

		foreach ( $font_declarations as $font_url ) {

			$url_structured = parse_url( $font_url );
			parse_str( $url_structured['query'], $query );
			$font_title = explode( ':', $query['family'] );
			$font_title = explode( ' ', $font_title[0] );
			$font_title = strtolower( implode( '_', $font_title ) );

			$file_dir        = $files_dir . $font_title . '/';
			$stored_file_uri = $stored_files_uri . $font_title . '/';

			$font_api_response = wp_remote_get(
				esc_url_raw( $font_url ),
				array(
					'headers' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
				)
			);
			$font_content      = wp_remote_retrieve_body( $font_api_response );

			$local_css = $this->rewrite_google_fonts_files( $font_content, $font_title, $file_dir, $stored_file_uri );

			if ( $local_css ) {
				$html = str_replace( $font_url, $local_css, $html );
			}
		}

		return $html;
	}

	/**
	 * Rewriting .css file contents with local font files
	 *
	 * @param $css
	 * @param $font_title
	 * @param $file_dir
	 * @param $stored_files_uri
	 *
	 * @return false|string
	 */
	public function rewrite_google_fonts_files( $css, $font_title, $file_dir, $stored_files_uri ) {
		$font_declarations = array();

		// Extract Google Fonts declarations from css file
		$pattern = '/url\((https:\/\/fonts\.gstatic\.com\/[^)]+)\)/';
		preg_match_all( $pattern, $css, $font_declarations );

		foreach ( $font_declarations[0] as $font_declaration ) {

			$clean_font_url = str_replace( array( 'url(', ')' ), '', $font_declaration );
			$filename       = basename( $clean_font_url );

			$local_font_file = $this->download_files_locally( $clean_font_url, $file_dir, $filename );

			if ( $local_font_file ) {
				$css = str_replace( $clean_font_url, $stored_files_uri . $filename, $css );
			}
		}

		$local_css_file_name = $font_title . '.css';
		$local_css_file_dir  = $file_dir . $local_css_file_name;
		$local_css_file_uri  = $stored_files_uri . $local_css_file_name;

		$wp_filesystem = breeze_get_filesystem();

		if ( $wp_filesystem->exists( $file_dir ) ) {
			$wp_filesystem->put_contents( $local_css_file_dir, $css );
		}

		if ( $wp_filesystem->exists( $local_css_file_dir ) ) {
			return $local_css_file_uri;
		}

		return false;
	}

	/**
	 * Extract Google Tag Manager files
	 *
	 * @param $html
	 * @param $file_dir
	 * @param $stored_files_uri
	 *
	 * @return array|false|string|string[]
	 */
	public function extract_gtm( $html, $file_dir, $stored_files_uri ) {
		$gtm_url        = $this->cdn_gtm_js_file;
		$gtag_url       = $this->cdn_gtm_js_route;
		$gtm_id_pattern = '/\'GTM-(.*?)\'/';

		$gtag_id_pattern = "/gtag\('config', '([A-Za-z0-9-]+)'\)/";

		preg_match( $gtm_id_pattern, $html, $gtm_id );
		preg_match( $gtag_id_pattern, $html, $gtag_id );

		$file_dir = $file_dir . 'google/';

		if ( isset( $gtm_id[1] ) ) {
			$configValue = $gtm_id[1];

			preg_match( '/' . preg_quote( $gtm_url, '/' ) . '/', $html, $gtm_file_url );

			if ( ! empty( $gtm_file_url ) ) {
				$gtm_file_url = $gtm_file_url[0] . '?id=GTM-' . $configValue;
				$local_file   = $this->download_files_locally( $gtm_file_url, $file_dir, 'gtm.js', '.js' );
				$log          = 'User: ' . $_SERVER['REMOTE_ADDR'] . ' - ' . date( 'F j, Y, g:i a' ) . PHP_EOL .
						'Attempt: gtm_not_empty' . PHP_EOL .
						'URL Gtm: ' . print_r( $gtm_file_url, true ) . PHP_EOL;

				if ( $local_file ) {
					$local_file_url = $stored_files_uri . 'google/gtm.js';

					$html = str_replace( $gtm_url, $local_file_url, $html );
				}
			}
		}

		if ( isset( $gtag_id[1] ) ) {
			$configValue = $gtag_id[1];

			preg_match( '/' . preg_quote( $gtag_url, '/' ) . '/', $html, $gtag_file_url );

			if ( ! empty( $gtag_file_url[0] ) ) {
				$gtag_file_url = $gtag_file_url[0] . '?id=' . $configValue;
				$local_file    = $this->download_files_locally( $gtag_file_url, $file_dir, 'gtag.js', '.js' );

				if ( $local_file ) {
					$local_file_url = $stored_files_uri . 'google/gtag.js';

					$html = str_replace( $gtag_url, $local_file_url, $html );
				}
			}
		}

		return $html;
	}


	/**
	 * Extract Google Analytics Js locally
	 *
	 * @param $html
	 * @param $file_dir
	 * @param $stored_files_uri
	 *
	 * @return array|mixed|string|string[]
	 */
	public function extract_google_analytics( $html, $file_dir, $stored_files_uri ) {

		$file_dir         = $file_dir . 'google/';
		$stored_files_uri = $stored_files_uri . 'google/';

		// Extract the Google Analytics script URLs using script tags
		$pattern = '/https:\/\/www.google-analytics.com\/analytics.js/i';
		preg_match_all( $pattern, $html, $matches );

		$analytics_script_urls = $matches[0];

		foreach ( $analytics_script_urls as $analytics_url ) {
			$filename = basename( $analytics_url );

			$local_analytics_file = $this->download_files_locally( $analytics_url, $file_dir, $filename, '.js' );

			if ( $local_analytics_file ) {
				$local_analytics_url = $stored_files_uri . $filename;
				$html                = str_replace( $analytics_url, $local_analytics_url, $html );
			}
		}

		return $html;
	}


	/**
	 * Extract Facebook Pixel Files
	 *
	 * @param $html
	 * @param $file_dir
	 * @param $stored_files_uri
	 *
	 * @return array|false|string|string[]
	 */
	public function extract_facebook_pixel( $html, $file_dir, $stored_files_uri ) {
		$url = $this->cdn_pixel_file_url;

		$pixel_pattern = '/https:\/\/connect\.facebook\.net\/[a-zA-Z_]+\/fbevents\.js/';
		preg_match_all( $pixel_pattern, $html, $fb_pixel_file_url );

		if ( ! empty( $fb_pixel_file_url[0][0] ) ) {

			$file_dir   = $file_dir . 'facebook/';
			$local_file = $this->download_files_locally( $fb_pixel_file_url[0][0], $file_dir, 'fbevents.js', '.js' );

			if ( $local_file ) {
				$local_file_url = $stored_files_uri . 'facebook/fbevents.js';

				return str_replace( $fb_pixel_file_url[0][0], $local_file_url, $html );
			}
		}

		return $html;
	}


	// Helper Functions

	/**
	 * Helper to download files locally (be it font or others)
	 *
	 * @param $url
	 * @param $file_dir
	 * @param $file_name
	 *
	 * @return bool|false
	 */
	public function download_files_locally( $url, $file_dir, $file_name, $file_type = '.css' ) {
		$wp_filesystem = breeze_get_filesystem();

		if ( ! $wp_filesystem->exists( $file_dir ) ) {
			// Use PHP filesystem function with FS_CHMOD_DIR. $wp_filesystem->mkdir does not support a recursive flag.
			mkdir( $file_dir, defined( 'FS_CHMOD_DIR' ) ? FS_CHMOD_DIR : 0775, true );
		}

		if ( $file_type = '.css' ) {
			$max_age_in_seconds = 7 * 24 * 60 * 60;
		} else {
			$max_age_in_seconds = 30 * 24 * 60 * 60;
		}

		$local_file_path = $file_dir . $file_name;

		// Check if the file exists and is less than 1 week old.
		if (
			$wp_filesystem->exists( $local_file_path ) &&
			time() - filemtime( $local_file_path ) < $max_age_in_seconds
		) {
			return true; // File is already up-to-date
		}

		// Validate the url.
		if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
			return false;
		}

		$original_file_content = file_get_contents( $url );

		if ( ! $original_file_content ) {
			return false;
		}

		// Write the file.
		$result = $wp_filesystem->put_contents( $local_file_path, $original_file_content );

		// Check if file was created successfully.
		if (
			! $result ||
			! $wp_filesystem->exists( $local_file_path )
		) {
			return false;
		}

		return true;
	}

	/**
	 * Function to delete temporary files
	 *
	 * @return bool
	 */
	public static function cleanup_all_extra_folder() {
		$wp_filesystem = breeze_get_filesystem();

		$ret = true;

		$folder = untrailingslashit( WP_CONTENT_DIR ) . '/uploads/breeze';

		if ( ! $wp_filesystem->delete( $folder, true ) ) {
			$ret = false;
		}

		/**
		 * For cache folder we only delete specific folders since the folder is being used by other plugins.
		 */
		$folder = untrailingslashit( WP_CONTENT_DIR ) . '/cache/breeze'; // HTML cache

		if ( ! $wp_filesystem->delete( $folder, true ) ) {
			$ret = false;
		}

		$folder = untrailingslashit( WP_CONTENT_DIR ) . '/cache/breeze-extra'; // Gravatars.

		if ( ! $wp_filesystem->delete( $folder, true ) ) {
			$ret = false;
		}

		$folder = untrailingslashit( WP_CONTENT_DIR ) . '/cache/breeze-minification'; // CSS/JS minified files.

		if ( ! $wp_filesystem->delete( $folder, true ) ) {
			$ret = false;
		}

		$folder = untrailingslashit( WP_CONTENT_DIR ) . '/cache/uncss'; // Clean of unneeded CSS.

		if ( ! $wp_filesystem->delete( $folder, true ) ) {
			$ret = false;
		}

		$folder = untrailingslashit( WP_CONTENT_DIR ) . '/cache'; // Cache folder in wp-content
		if ( true === breeze_is_folder_empty( $folder ) ) {
			$wp_filesystem->delete( $folder, true );
		}

		return $ret;
	}
}
