<?php

if ( class_exists( 'WP_Customize_Control' ) && !class_exists( 'SiteOrigin_Customize_Fonts_Control' ) ) {
	/**
	 * A customizer control for choosing web fonts
	 */
	class SiteOrigin_Customize_Fonts_Control extends WP_Customize_Control {
		public $id;
		public $type;
		
		public function __construct( $manager, $id, $args = array() ) {
			// Let other themes and plugins process the web fonts array
			$google_web_fonts = include __DIR__ . '/google-fonts.php';

			// Add the default fonts
			$choices = array(
				'Helvetica Neue' => 'Helvetica Neue',
				'Lucida Grande' => 'Lucida Grande',
				'Arial' => 'Arial',
				'Verdana' => 'Verdana',
				'Georgia' => 'Georgia',
				'Courier New' => 'Courier New',
			);

			foreach ( $google_web_fonts as $font => $variants ) {
				foreach ( $variants as $variant ) {
					if ( $variant == 'regular' || $variant == 400 ) {
						$choices[ $font ] = $font;
					} else {
						$choices[ $font . ':' . $variant ] = $font . ' (' . $variant . ')';
					}
				}
			}

			$args = wp_parse_args( $args, array(
				'type' => 'select',
				'choices' => $choices,
			) );
			parent::__construct( $manager, $id, $args );
		}

								/**
								 * Render the control. Renders the control wrapper, then calls $this->render_content().
								 */
								protected function render() {
									$id = 'customize-control-' . str_replace( '[', '-', str_replace( ']', '', $this->id ) );
									$class = 'customize-control customize-control-' . $this->type . ' customize-control-font';

									?>
		<li id="<?php echo esc_attr( $id ); ?>" class="<?php echo esc_attr( $class ); ?>">
			<?php $this->render_content(); ?>
		</li>
		<?php
								}
	}
}

if ( !class_exists( 'SiteOrigin_Customizer_CSS_Builder' ) ) {
	/**
	 * This is used for building custom CSS.
	 */
	class SiteOrigin_Customizer_CSS_Builder {
		private $css;
		private $raw_css;
		private $google_fonts;
		private $defaults;

		// These are web safe fonts
		public static $web_safe = array(
			'Helvetica Neue' => 'Arial, Helvetica, Geneva, sans-serif',
			'Lucida Grande' => 'Lucida, Verdana, sans-serif',
			'Arial' => 'Arial, Helvetica, sans-serif',
			'Verdana' => 'Verdana, Geneva, sans-serif',
			'Georgia' => '"Times New Roman", Times, serif',
			'Courier New' => 'Courier, mono',
		);

		public function __construct( $defaults ) {
			$this->css = array();
			$this->raw_css = '';
			$this->google_fonts = array();
			$this->defaults = $defaults;
		}

		/**
		 * Echo all the CSS
		 */
		public function css() {
			// Start by importing Google web fonts
			$return = '<style type="text/css" id="customizer-css">';

			if ( apply_filters( 'origami_import_google_fonts', true ) ) {
				$import = array();

				foreach ( $this->google_fonts as $font ) {
					$import[ ] = urlencode( $font[ 0 ] ) . ':' . $font[ 1 ];
				}
				$import = array_unique( $import );

				if ( ! empty( $import ) ) {
					$return .= '@import url(//fonts.googleapis.com/css?family=' . implode( '|', $import ) . '&display=block); ';
				}
			}

			foreach ( $this->css as $selector => $rules ) {
				$return .= $selector . ' { ' . implode( '; ', $rules ) . ' } ';
			}

			if ( ! empty( $this->raw_css ) ) {
				$return .= $this->raw_css;
			}

			$return .= '</style>';

			return $return;
		}

		/**
		 * Add a raw CSS value
		 */
		public function add_css( $selector, $property, $value ) {
			if ( empty( $value ) ) {
				return;
			}

			$selector = preg_replace( '/\s+/m', ' ', $selector );

			if ( $property == 'font' ) {
				if ( strpos( $value, ':' ) !== false ) {
					list( $family, $variant ) = explode( ':', $value, 2 );
				} else {
					$family = $value;
					$variant = 400;
				}

				if ( ! empty( self::$web_safe[ $family ] ) ) {
					$family = '"' . $family . '", ' . self::$web_safe[ $family ];
				} else {
					$this->google_fonts[ ] = array( $family, $variant );
					$family = '"' . $family . '"';
				}

				$this->add_css( $selector, 'font-family', $family );

				if ( $variant != 400 ) {
					$this->add_css( $selector, 'font-weight', $variant );
				}

				return;
			}

			if ( empty( $this->css[ $selector ] ) ) {
				$this->css[ $selector ] = array();
			}

			$this->css[ $selector ][ ] = $property . ': ' . $value;
		}

		/**
		 * Add some basic, raw CSS.
		 *
		 * @param string $css The raw CSS.
		 */
		public function add_raw_css( $css ) {
			$this->raw_css .= ' ' . $css;
		}

		/**
		 * Adds a Google web font or web safe font
		 *
		 * @param string $selector The selector we want to use the web font with.
		 * @param string $mod      The theme mod where the font is stored.
		 */
		public function add_web_font( $selector, $mod ) {
			$font = get_theme_mod( $mod );

			if ( empty( $font ) || empty( $this->defaults[$mod] ) || $font == $this->defaults[$mod] ) {
				return;
			}

			if ( empty( $this->css[ $selector ] ) ) {
				$this->css[ $selector ] = array();
			}

			if ( strpos( $font, ':' ) !== false ) {
				list( $family, $variant ) = explode( ':', $font, 2 );
			} else {
				$variant = 400;
				$family = $font;
			}

			if ( ! empty( self::$web_safe[ $family ] ) ) {
				$family = '"' . $family . '", ' . self::$web_safe[ $family ];
			} else {
				$this->google_fonts[ ] = array( $family, $variant );
				$family = '"' . $family . '"';
			}

			$this->add_css( $selector, 'font-family', $family );

			if ( ! empty( $variant ) ) {
				if ( $variant != 400 && $variant != 'regular' ) {
					if ( ! is_numeric( $variant ) ) {
						$variant = filter_var( $variant, FILTER_SANITIZE_NUMBER_INT );
						$this->add_css( $selector, 'font-style', 'italic' );
					}
					$this->add_css( $selector, 'font-weight', $variant );
				} else {
					$this->add_css( $selector, 'font-weight', 400 );
				}
			}
		}

		/**
		 * Adds a color property.
		 */
		public function add_color( $selector, $property, $mod ) {
			$color = get_theme_mod( $mod );

			if ( empty( $color ) || empty( $this->defaults[$mod] ) || $color == $this->defaults[$mod] ) {
				return;
			}

			$this->add_css( $selector, $property, $color );
		}

		/**
		 * Add an image URL
		 */
		public function add_image( $selector, $property, $mod ) {
			$image = get_theme_mod( $mod );

			if ( ! empty( $image ) ) {
				$this->add_css( $selector, $property, 'url("' . esc_url( $image ) . '")' );
			}
		}

		/**
		 * Adds a measurement property
		 *
		 * @param string $units
		 */
		public function add_measurement( $selector, $property, $mod, $units = 'px' ) {
			$value = get_theme_mod( $mod );
			$measurement = floatval( $value );

			if ( !is_float( $value ) || empty( $this->defaults[$mod] ) || $measurement == $this->defaults[$mod] ) {
				return;
			}

			$this->add_css( $selector, $property, $measurement . $units );
		}

		/**
		 * Convert a HEX value to an RGB array
		 *
		 * @return array
		 */
		public static function hex2rgb( $hex ) {
			$hex = str_replace( '#', '', $hex );

			if ( strlen( $hex ) == 3 ) {
				$r = hexdec( substr( $hex, 0, 1 ) . substr( $hex, 0, 1 ) );
				$g = hexdec( substr( $hex, 1, 1 ) . substr( $hex, 1, 1 ) );
				$b = hexdec( substr( $hex, 2, 1 ) . substr( $hex, 2, 1 ) );
			} else {
				$r = hexdec( substr( $hex, 0, 2 ) );
				$g = hexdec( substr( $hex, 2, 2 ) );
				$b = hexdec( substr( $hex, 4, 2 ) );
			}

			return array( $r, $g, $b );
		}
	}
}

/**
 * Sanitize a Google font.
 *
 * @param string $font
 *
 * @return string
 */
function siteorigin_customizer_sanitize_google_font( $font ) {
	// Check the default fonts too.
	$default_fonts = array(
		'Helvetica Neue' => 'Helvetica Neue',
		'Lucida Grande' => 'Lucida Grande',
		'Arial' => 'Arial',
		'Verdana' => 'Verdana',
		'Georgia' => 'Georgia',
		'Courier New' => 'Courier New',
	);

	$google_fonts = include __DIR__ . '/google-fonts.php';
	$font_name_parts = explode( ':', $font, 2 );
	$font_name = $font_name_parts[0];

	if ( empty( $google_fonts[$font_name] ) && empty( $default_fonts[$font_name] ) ) {
		$font = '';
	}

	return $font;
}

/**
 * Sanitize a float value
 *
 * @return float
 */
function siteorigin_customizer_sanitize_floatval( $value ) {
	return floatval( $value );
}

/**
 * Sanitize an integer value
 *
 * @return int
 */
function siteorigin_customizer_sanitize_intval( $value ) {
	return intval( $value );
}

/**
 * Sanitize an image URL
 *
 * @return string
 */
function siteorigin_customizer_sanitize_image( $image ) {
	return esc_url_raw( $image );
}

if ( !class_exists( 'SiteOrigin_Customizer_Helper' ) ) {
	class SiteOrigin_Customizer_Helper {
		private $theme;
		private $settings;
		private $sections;
		private $defaults;

		public function __construct( $settings = array(), $sections = array(), $theme = 'generic', $root_url = false, $make_single = true ) {
			// Give child themes a chance to filter this.
			$this->theme = $theme;
			$this->defaults = array();
			$this->settings = array();

			$this->add_sections( $sections );
			$this->add_settings( $settings );

			// Add a script that will help us with our previews
			add_action( 'customize_preview_init', array( $this, 'enqueue' ) );
			add_action( 'customize_controls_enqueue_scripts', array( $this, 'admin_enqueue' ) );

			if ( $make_single ) {
				global $siteorigin_customize_helper_single;
				$siteorigin_customize_helper_single = $this;
			}
		}

		/**
		 * Get the global instance of the siteorigin customize helper
		 *
		 * @return mixed
		 */
		public static function single() {
			global $siteorigin_customize_helper_single;

			if ( empty( $siteorigin_customize_helper_single ) ) {
				new SiteOrigin_Customizer_Helper();
			}

			return $siteorigin_customize_helper_single;
		}

		/**
		 * Add sections to the customizer helper.
		 *
		 * @param array $sections
		 */
		public function add_sections( $sections = array() ) {
			$sections = apply_filters( $this->theme . '_siteorigin_theme_customizer_sections', $sections );
			$this->sections = wp_parse_args( $sections, $this->sections );
		}

		/**
		 * Add settings to the customzier helper.
		 *
		 * @param array $settings
		 */
		public function add_settings( $settings = array() ) {
			$settings = apply_filters( $this->theme . '_siteorigin_theme_customizer_settings', $settings );

			foreach ( $settings as $section_id => $section_settings ) {
				foreach ( $section_settings as $id => $setting ) {
					$setting['section'] = $section_id;
					$this->settings[$section_id . '_' . $id] = $setting;

					if ( ! empty( $setting['default'] ) ) {
						$this->defaults[$section_id . '_' . $id] = $setting['default'];
					}
				}
			}
		}

		/**
		 * Registers all the customizations with the WordPress customize manager. Should be called by function tied to customize_register action.
		 *
		 * @param WP_Customize_Manager $wp_customize
		 */
		public function customize_register( $wp_customize ) {
			// Add the panel that will contain all the theme settings
			$theme = wp_get_theme();
			$wp_customize->add_panel( 'siteorigin_theme_settings', array(
				'priority'       => 50,
				'capability'     => 'edit_theme_options',
				'title'          => __( 'Theme Design', 'origami' ),
				'description'    => sprintf( __( 'Theme Specific Customizations For %s.', 'origami' ), $theme->get( 'Name' ) ),
			) );

			// Start by registering all the sections
			foreach ( $this->sections as $id => $section ) {
				$section = wp_parse_args( $section, array(
					'panel' => 'siteorigin_theme_settings',
				) );
				$wp_customize->add_section( $id, $section );
			}

			static $priority = 0;

			// Now add all the settings
			foreach ( $this->settings as $id => $setting ) {
				switch( $setting['type'] ) {
					case 'font' :
						$sanitize_callback = 'siteorigin_customizer_sanitize_google_font';
						break;

					case 'color' :
						$sanitize_callback = 'sanitize_hex_color';
						break;

					case 'measurement' :
						$sanitize_callback = 'siteorigin_customizer_sanitize_floatval';
						break;

					case 'image' :
						$sanitize_callback = 'siteorigin_customizer_sanitize_image';
						break;

					default:
						$sanitize_callback = 'sanitize_text_field';
						break;
				}

				$wp_customize->add_setting( $id, array(
					'default' => ! empty( $setting['default'] ) ? $setting['default'] : '',
					'sanitize_callback' => $sanitize_callback,
				) );

				// Can't use live changes with a callback
				if ( ! empty( $setting['callback'] ) ) {
					$setting['no_live'] = true;
				}

				// Set $setting['description' ] if this setting doesn't have a description
				if ( ! isset( $setting['description' ] ) ) {
					$setting['description'] = '';
				}

				// Now lets add a control for this setting
				switch( $setting['type'] ) {
					case 'font':
						$wp_customize->add_control( new SiteOrigin_Customize_Fonts_Control( $wp_customize, $this->theme . '_' . $id, array(
							'label' => $setting['title'],
							'section' => $setting['section'],
							'settings' => $id,
							'priority' => $priority++,
							'description' => esc_html( $setting['description'] ),
						) ) );
						break;

					case 'color':
						$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, $this->theme . '_' . $id, array(
							'label' => $setting['title'],
							'section' => $setting['section'],
							'settings' => $id,
							'priority' => $priority++,
							'description' => esc_html( $setting['description'] ),
						) ) );

						if ( empty( $setting['no_live'] ) ) {
							$wp_customize->get_setting( $id )->transport = 'postMessage';
						}
						break;

					case 'measurement':
						$wp_customize->add_control( $id, array(
							'label' => $setting['title'],
							'section' => $setting['section'],
							'type'    => 'text',
							'priority' => $priority++,
							'description' => esc_html( $setting['description'] ),
						) );

						if ( empty( $setting['no_live'] ) ) {
							$wp_customize->get_setting( $id )->transport = 'postMessage';
						}
						break;

					case 'image':
						$wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, $this->theme . '_' . $id, array(
							'label' => $setting['title'],
							'section' => $setting['section'],
							'settings' => $id,
							'priority' => $priority++,
							'description' => esc_html( $setting['description'] ),
						) ) );
						break;

					case 'image_select':
						$wp_customize->add_control( new SiteOrigin_Customize_Image_Select_Control( $wp_customize, $this->theme . '_' . $id, array(
							'label' => $setting['title'],
							'section' => $setting['section'],
							'settings' => $id,
							'priority' => $priority++,
							'description' => esc_html( $setting['description'] ),
						) ) );
						break;

					default:
						$wp_customize->add_control( $id, array(
							'label' => $setting['title'],
							'section' => $setting['section'],
							'type'    => $setting['type'],
							'priority' => $priority++,
							'choices' => isset( $setting['choices'] ) ? $setting['choices'] : null,
							'description' => esc_html( $setting['description'] ),
						) );
						break;
				}
			}
		}

		/**
		 * Create the CSS builder with all the current values
		 *
		 * @return SiteOrigin_CSS_Builder
		 */
		public function create_css_builder() {
			$builder = new SiteOrigin_Customizer_CSS_Builder( $this->defaults );

			foreach ( $this->settings as $id => $setting ) {
				if ( ! empty( $setting['selector'] ) ) {
					foreach ( (array) $setting['selector'] as $selector ) {
						switch( $setting['type'] ) {
							case 'font':
								$builder->add_web_font( $selector, $id );
								break;

							case 'color':
								foreach ( (array) $setting['property'] as $property ) {
									$builder->add_color( $selector, $property, $id );
								}
								break;

							case 'measurement':
								foreach ( (array) $setting['property'] as $property ) {
									$builder->add_measurement( $selector, $property, $id, $setting['unit'] );
								}
								break;

							case 'image':
								foreach ( (array) $setting['property'] as $property ) {
									$builder->add_image( $selector, $property, $id );
								}
								break;

							default:
								if ( isset( $setting['property'] ) ) {
									foreach ( (array) $setting['property'] as $property ) {
										$builder->add_css( $selector, $property, get_theme_mod( $id ) );
									}
								}
								break;
						}
					}
				}

				if ( isset( $setting['callback'] ) ) {
					$val = get_theme_mod( $id );

					if ( isset( $setting['default'] ) && $val != $setting['default'] ) {
						call_user_func( $setting['callback'], $builder, $val, array_merge( $setting, array( 'id' => $id ) ) );
					}
				}
			}

			$builder = apply_filters( $this->theme . '_siteorigin_customizer_custom_css', $builder, $this->settings, $this->defaults );

			return $builder;
		}

		/**
		 * Enqueue the customizer scripts
		 */
		public function enqueue() {
			wp_enqueue_script( 'siteorigin-customizer-preview', get_template_directory_uri() . '/inc/customizer/js/live-customizer' . SITEORIGIN_THEME_JS_PREFIX . '.js', array( 'jquery', 'customize-preview' ), SITEORIGIN_THEME_VERSION );
			wp_localize_script( 'siteorigin-customizer-preview', 'customizeSettings', $this->settings );
		}

		/**
		 * Enqueue scripts for the actual customizer admin
		 */
		public function admin_enqueue() {
			wp_enqueue_script( 'siteorigin-customizer-admin', get_template_directory_uri() . '/inc/customizer/js/admin' . SITEORIGIN_THEME_JS_PREFIX . '.js', array( 'jquery', 'customize-controls' ), SITEORIGIN_THEME_VERSION );
			wp_localize_script( 'siteorigin-customizer-admin', 'soCustomizeAdmin', array(
				'confirm' => __( 'Are you sure you want to reset your theme customizations?', 'origami' ),
				'button' => __( 'Reset Customizations', 'origami' ),
				'action' => wp_nonce_url(
					add_query_arg( array(
						'return' => add_query_arg( false, false ),
						'action' => 'so_customize_reset',
					), admin_url( 'admin-ajax.php' ) ),
					'so_customize_reset'
				),
			) );

			wp_enqueue_style( 'siteorigin-customizer-admin', get_template_directory_uri() . '/inc/customizer/css/admin.css', array( ), SITEORIGIN_THEME_VERSION );
		}

		/**
		 * Reset all defaults
		 */
		public function reset_defaults() {
			foreach ( $this->settings as $id => $values ) {
				remove_theme_mod( $id );
			}
		}
	}
}
