<?php
if ( ! class_exists('Divi_Layouts_Extended_Import') ) {
	require_once(ABSPATH . 'wp-admin/includes/file.php');
	class Divi_Layouts_Extended_Import {

		protected function set_filesystem() {
			global $wp_filesystem;
			add_filter( 'filesystem_method', array( $this, 'replace_filesystem_method' ) );
			WP_Filesystem();
			return $wp_filesystem;
		}

		protected function get_filesystem() {
			static $filesystem = null;

			if ( null === $filesystem ) {
				$filesystem = $this->set_filesystem();
			}

			return $filesystem;
		}

		public function replace_filesystem_method() {
			return 'direct';
		}

		public function import_post($data) {
			if ( isset( $data['data'] ) ) {

				if ( ! empty( $data['images'] ) ) {
					$data['images'] = $this->upload_image( $data['images'] );
				}

				foreach ( $data['data'] as $key => $element ) {
					$title 	 = $element['post_title'];
					$content = $this->replace_images( $element['post_content'], $data['images'] );
					$post_data = array(
					 	'post_title'    	=> $title,
					 	'post_content'    	=> $content,
						'post_status'  	 	=> 'publish', 
						'post_type'   		=> 'et_pb_layout'
					 );
					$post_id = wp_insert_post( $post_data );

					if ( isset( $post_id ) && '' !== $post_id ) {

						//Set Post Meta
						if ( isset( $element['post_meta'] ) && is_array( $element['post_meta'] ) ) {
							foreach ( $element['post_meta'] as $meta_key => $meta_value ) {
								$meta_key = sanitize_text_field( $meta_key );

								if ( count( $meta_value ) < 2 ) {
									$meta_value = wp_kses_post( $meta_value[0] );
								} else {
									$meta_value = array_map( 'wp_kses_post', $meta_value );
								}

								update_post_meta( $post_id, $meta_key, $meta_value );

							/*	Need to write code when post meta is thumbnail id once ET releases fix for featured image import.
								if( '_thumbnail_id' === $meta_key ) {
									update_post_meta( $post_id, $meta_key, wp_slash( $meta_value[0] ) );
								}*/
							}
						}

						//Set Terms
						if ( isset( $element['terms'] ) && is_array( $element['terms'] ) ) {
					
							$processed_terms = array();

							foreach ( $element['terms'] as $term ) {

								if ( empty( $term['parent'] ) ) {
									$parent = 0;
								} else {
									if ( isset( $term['all_parents'] ) && ! empty( $term['all_parents'] ) ) {
										$this->restore_parent_categories( $term['all_parents'], $term['taxonomy'] );
									}

									$parent = term_exists( $term['parent'], $term['taxonomy'] );

									if ( is_array( $parent ) ){
										$parent = $parent['term_id'];
									}
								}

								if ( ! $insert = term_exists( $term['slug'], $term['taxonomy'] ) ) {
									$insert = wp_insert_term( $term['name'], $term['taxonomy'], array(
										'slug'        => $term['slug'],
										'description' => $term['description'],
										'parent'      => intval( $parent ),
									) );
								}

								if ( is_array( $insert ) && ! is_wp_error( $insert ) ) {
									$processed_terms[$term['taxonomy']][] = $term['slug'];
								}
							}

							// Set post terms.
							foreach ( $processed_terms as $taxonomy => $ids ) {
								wp_set_object_terms( $post_id, $ids, $taxonomy );
							}
						}

						//Set Presets
						if ( isset( $element['presets'] ) && is_array( $element['presets'] ) ) {
							$this->import_global_presets($element['presets']);
						}


						//Set Global Color
						if ( isset( $element['global_colors'] ) && is_array( $element['global_colors'] ) ) {
							$this->import_global_colors($element['global_colors']);
						}

						return true;

						break;
					}
				}
			}
		}

		public function restore_parent_categories( $parents_array, $taxonomy ) {
			foreach( $parents_array as $slug => $category_data ) {
				$current_category = term_exists( $slug, $taxonomy );

				if ( ! is_array( $current_category ) ) {
					$parent_id = 0 !== $category_data['parent'] ? term_exists( $category_data['parent'], $taxonomy ) : 0;
					wp_insert_term( $category_data['name'], $taxonomy, array(
						'slug'        => $slug,
						'description' => $category_data['description'],
						'parent'      => is_array( $parent_id ) ? $parent_id['term_id'] : $parent_id,
					) );
				} else if ( ( ! isset( $current_category['parent'] ) || 0 === $current_category['parent'] ) && 0 !== $category_data['parent'] ) {
					$parent_id = 0 !== $category_data['parent'] ? term_exists( $category_data['parent'], $taxonomy ) : 0;
					wp_update_term( $current_category['term_id'], $taxonomy, array( 'parent' => is_array( $parent_id ) ? $parent_id['term_id'] : $parent_id ) );
				}
			}
		}

		public function import_global_presets( $presets ) {
			if ( ! is_array( $presets ) ) {
				return false;
			}

			$all_modules            = ET_Builder_Element::get_modules();
			$module_presets_manager = ET_Builder_Global_Presets_Settings::instance();
			$global_presets         = $module_presets_manager->get_global_presets();
			$presets_to_import      = array();

			foreach ( $presets as $module_type => $module_presets ) {
				$presets_to_import[ $module_type ] = array(
					'presets' => array(),
				);

				if ( ! isset( $global_presets->$module_type->presets ) ) {
					$initial_preset_structure = ET_Builder_Global_Presets_Settings::generate_module_initial_presets_structure( $module_type, $all_modules );

					$global_presets->$module_type = $initial_preset_structure;
				}

				$local_presets      = $global_presets->$module_type->presets;
				$local_preset_names = array();

				foreach ( $local_presets as $preset ) {
					array_push( $local_preset_names, $preset->name );
				}

				foreach ( $module_presets['presets'] as $preset_id => $preset ) {
					$imported_name = sanitize_text_field( $preset['name'] );
					$name          = in_array( $imported_name, $local_preset_names )
						? $imported_name . ' ' . esc_html__( 'imported', 'et-core' )
						: $imported_name;

					$presets_to_import[ $module_type ]['presets'][ $preset_id ] = array(
						'name'     => $name,
						'created'  => time() * 1000,
						'updated'  => time() * 1000,
						'version'  => $preset['version'],
						'settings' => $preset['settings'],
					);
				}
			}

			// Merge existing Global Presets with imported ones
			foreach ( $presets_to_import as $module_type => $module_presets ) {
				foreach ( $module_presets['presets'] as $preset_id => $preset ) {
					$global_presets->$module_type->presets->$preset_id           = (object) array();
					$global_presets->$module_type->presets->$preset_id->name     = sanitize_text_field( $preset['name'] );
					$global_presets->$module_type->presets->$preset_id->created  = $preset['created'];
					$global_presets->$module_type->presets->$preset_id->updated  = $preset['updated'];
					$global_presets->$module_type->presets->$preset_id->version  = $preset['version'];
					$global_presets->$module_type->presets->$preset_id->settings = (object) array();

					foreach ( $preset['settings'] as $setting_name => $value ) {
						$setting_name_sanitized = sanitize_text_field( $setting_name );
						$value_sanitized        = sanitize_text_field( $value );

						$global_presets->$module_type->presets->$preset_id->settings->$setting_name_sanitized = $value_sanitized;
					}

					// Inject Global colors into imported presets.
					$global_presets->$module_type->presets->$preset_id->settings = ET_Builder_Global_Presets_Settings::maybe_set_global_colors( $global_presets->$module_type->presets->$preset_id->settings );
				}
			}

			et_update_option( ET_Builder_Global_Presets_Settings::GLOBAL_PRESETS_OPTION, $global_presets );

			$global_presets_history = ET_Builder_Global_Presets_History::instance();
			$global_presets_history->add_global_history_record( $global_presets );

			return true;
		}

		public function import_global_colors( $incoming_global_colors ) {
			$global_colors = array();

			foreach ( $incoming_global_colors as $incoming_gcolor ) {
				$key                   = et_()->sanitize_text_fields( $incoming_gcolor[0] );
				$global_colors[ $key ] = et_()->sanitize_text_fields( $incoming_gcolor[1] );
			}

			$stored_global_colors = et_builder_get_all_global_colors();

			if ( ! empty( $stored_global_colors ) ) {
				$global_colors = array_merge( $global_colors, $stored_global_colors );
			}

			et_update_option( 'et_global_colors', $global_colors );
		}


		public function replace_images( $content, $images ) {
			foreach ( $images as $key => $image ) {
				if ( isset( $image['replacement_id'] ) && isset( $image['id'] ) ) {
					$search      = $image['id'];
					$replacement = $image['replacement_id'];
					$content     = preg_replace( "/(gallery_ids=.*){$search}(.*\")/", "\${1}{$replacement}\${2}", $content );
				}
				str_replace( $image['url'], $image['replacement_url'], $content );
			}
			return $content;
		}

		public function upload_image( $images ) {
			$filesystem = $this->get_filesystem();
			foreach ( $images as $key => $image ) {
				$basename    = sanitize_file_name( wp_basename( $image['url'] ) );
				$attachments = get_posts( array(
					'posts_per_page' => -1,
					'post_type'      => 'attachment',
					'meta_key'       => '_wp_attached_file',
					'meta_value'     => pathinfo( $basename, PATHINFO_FILENAME ),
					'meta_compare'   => 'LIKE',
				) );
				$id = 0;
				$url = '';

				// Avoid duplicates.
				if ( ! is_wp_error( $attachments ) && ! empty( $attachments ) ) {
					foreach ( $attachments as $attachment ) {
						$attachment_url = wp_get_attachment_url( $attachment->ID );
						$file           = get_attached_file( $attachment->ID );
						$filename       = sanitize_file_name( wp_basename( $file ) );

						// Use existing image only if the content matches.
						if ( $filesystem->get_contents( $file ) === base64_decode( $image['encoded'] ) ) {
							$id = isset( $image['id'] ) ? $attachment->ID : 0;
							$url = $attachment_url;

							break;
						}
					}
				}

				// Create new image.
				if ( empty( $url ) ) {
					$temp_file = wp_tempnam();
					$filesystem->put_contents( $temp_file, base64_decode( $image['encoded'] ) );
					$filetype = wp_check_filetype_and_ext( $temp_file, $basename );

					// Avoid further duplicates if the proper_file name match an existing image.
					if ( isset( $filetype['proper_filename'] ) && $filetype['proper_filename'] !== $basename ) {
						if ( isset( $filename ) && $filename === $filetype['proper_filename'] ) {
							// Use existing image only if the basenames and content match.
							if ( $filesystem->get_contents( $file ) === $filesystem->get_contents( $temp_file ) ) {
								$filesystem->delete( $temp_file );
								continue;
							}
						}
					}

					$file = array(
						'name'     => $basename,
						'tmp_name' => $temp_file,
					);
					require_once(ABSPATH . 'wp-admin/includes/media.php');
					require_once(ABSPATH . 'wp-admin/includes/file.php');
					require_once(ABSPATH . 'wp-admin/includes/image.php');

					$upload = media_handle_sideload( $file, 0 );

					if ( ! is_wp_error( $upload ) ) {
						// Set the replacement as an id if the original image was set as an id (for gallery).
						$id = isset( $image['id'] ) ? $upload : 0;
						$url = wp_get_attachment_url( $upload );
					} else {

						// Make sure the temporary file is removed if media_handle_sideload didn't take care of it.
						$filesystem->delete( $temp_file );
					}
				}

				// Only declare the replace if a url is set.
				if ( $id > 0 ) {
					$images[$key]['replacement_id'] = $id;
				}

				if ( ! empty( $url ) ) {
					$images[$key]['replacement_url'] = $url;
				}

				unset( $url );
			}

			return $images;
		}
	}
}