<?php
/**
 * Functions and custom controls for customizer
 *
 * @package Multi
 */

if ( ! defined( 'ABSPATH' ) ) {
	die;
}


if ( class_exists( 'WP_Customize_Control' ) ) {
	require get_theme_file_path( '/functions/class-multimagazine-customize-heading.php' );
	require get_theme_file_path( '/functions/class-multimagazine-range-control.php' );
	require get_theme_file_path( '/functions/class-multimagazine-colorcontrol.php' );
}

/**
 * Multi Customizer class.
 */
class Multimagazine_Customize {
	/**
	 * Customizer object.
	 *
	 * @var WP_Customize_Manager $wpc Customizer object.
	 */
	public $wpc;

	/**
	 * Multimagazine_Customize constructor.
	 */
	public function __construct() {
		global $wp_customize;
		$this->wpc = $wp_customize;
		add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_style' ) );
	}

	/**
	 * Returns a setting's default value from its matching theme constant.
	 *
	 * Setting keys keep their historical `multi_` / `pagination_` prefixes for
	 * backward compatibility, while the corresponding default constants are
	 * prefixed with `MULTIMAGAZINE_`. This maps a key to the correct constant.
	 *
	 * @param string $name Setting name.
	 * @return mixed Constant value when defined, empty string otherwise.
	 */
	private function setting_default( $name ) {
		$const = strtoupper( $name );
		if ( 0 === strpos( $const, 'MULTI_' ) ) {
			$const = 'MULTIMAGAZINE_' . substr( $const, 6 );
		} elseif ( 0 === strpos( $const, 'PAGINATION_' ) ) {
			$const = 'MULTIMAGAZINE_' . $const;
		}
		return defined( $const ) ? constant( $const ) : '';
	}

	/**
	 * Enqueues customizer styles
	 */
	public function enqueue_style() {
		$hash = sha1_file( get_template_directory() . '/css/customize.css' );
		wp_enqueue_style( 'multimagazine-customize', get_template_directory_uri() . '/css/customize.css?v=' . $hash, array(), 1 );
	}

	/**
	 * Prints a heading inside customizer panel
	 *
	 * @param string  $id Element id.
	 * @param string  $section Customizer section slug.
	 * @param string  $content Title text.
	 * @param integer $level Heading level.
	 */
	public function heading( $id, $section, $content, $level = 3 ) {

		$this->wpc->add_setting( $id, array( 'sanitize_callback' => 'sanitize_text_field' ) );
		$this->wpc->add_control(
			new Multimagazine_Customize_Heading(
				$this->wpc,
				$id,
				array(
					'content' => $content,
					'level'   => $level,
					'section' => $section,
				)
			)
		);
	}

	/**
	 * Registers checkbox setting
	 *
	 * @param string $name Setting name.
	 * @param string $section Customizer section slug.
	 * @param string $label Control label text.
	 * @param string $description Control description text.
	 */
	public function checkbox_setting( $name, $section, $label, $description = '' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'sanitize_callback' => array( 'Multimagazine_Sanitizer', 'checkbox' ),
				'default'           => $this->setting_default( $name ),
			)
		);
		$this->wpc->add_control(
			$name,
			array(
				'label'       => $label,
				'section'     => $section,
				'settings'    => $name,
				'type'        => 'checkbox',
				'description' => $description,
			)
		);
	}

	/**
	 * Range control
	 *
	 * @param string  $name Setting name.
	 * @param string  $section Customizer section slug.
	 * @param integer $min Minimum possible value.
	 * @param integer $max Maximum possible value.
	 * @param integer $step Step by which the value changes when user clicks the control's arrows.
	 * @param string  $label Control label text.
	 * @param string  $description Control description text.
	 * @param string  $transport Use 'postMessage' value to avoid reloading on change.
	 */
	public function range_setting( $name, $section, $min = 0, $max = 100, $step = 1, $label = '', $description = '', $transport = 'refresh' ) {
		$default = $this->setting_default( $name );
		$this->wpc->add_setting(
			$name,
			array(
				'sanitize_callback' => array( 'Multimagazine_Sanitizer', 'number_int' ),
				'default'           => $default,
				'transport'         => $transport,
			)
		);

		$this->wpc->add_control(
			new Multimagazine_Range_Control(
				$this->wpc,
				$name,
				array(
					'min'         => $min,
					'max'         => $max,
					'label'       => $label,
					'description' => $description,
					'section'     => $section,
					'step'        => $step,
					'default'     => $default,
				)
			)
		);
	}

	/**
	 * Select control
	 *
	 * @param String $name Setting name.
	 * @param String $section Customizer section slug.
	 * @param Array  $choices Associative array of choices.
	 * @param String $label Control label text.
	 * @param String $description Control description text.
	 * @param String $transport Use 'postMessage' value to avoid reloading on change.
	 */
	public function select_setting( $name, $section, $choices, $label, $description = '', $transport = 'refresh' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'sanitize_callback' => 'sanitize_text_field',
				'default'           => $this->setting_default( $name ),
				'transport'         => $transport,
			)
		);

		$this->wpc->add_control(
			$name,
			array(
				'label'       => $label,
				'section'     => $section,
				'settings'    => $name,
				'type'        => 'select',
				'choices'     => $choices,
				'description' => $description,
			)
		);
	}

	/**
	 * Registers color setting
	 *
	 * @param string $name Setting name.
	 * @param string $section Customizer section slug.
	 * @param string $label Control label text.
	 * @param string $description Control description text.
	 * @param string $transport Use 'postMessage' value to avoid reloading on change.
	 */
	public function color_setting( $name, $section, $label, $description = '', $transport = 'refresh' ) {
		$default = $this->setting_default( $name );
		$this->wpc->add_setting(
			$name,
			array(
				'sanitize_callback' => 'sanitize_hex_color',
				'default'           => $default,
				'transport'         => $transport,
			)
		);
		$setting_data = array(
			'label'    => $label,
			'section'  => $section,
			'settings' => $name,
		);

		if ( ! empty( $description ) ) {
			$setting_data['description'] = $description;
		}
		$this->wpc->add_control(
			new WP_Customize_Color_Control(
				$this->wpc,
				$name,
				$setting_data
			)
		);
	}

	/**
	 * Registers color alpha setting
	 *
	 * @param string $name Setting name.
	 * @param string $section Customizer section slug.
	 * @param string $label Control label text.
	 * @param string $description Control description text.
	 * @param string $transport Use 'postMessage' value to avoid reloading on change.
	 */
	public function color_alpha_setting( $name, $section, $label, $description = '', $transport = 'refresh' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'sanitize_callback' => 'sanitize_text_field',
				'default'           => $this->setting_default( $name ),
				'transport'         => $transport,
			)
		);
		$setting_data = array(
			'label'    => $label,
			'section'  => $section,
			'settings' => $name,
		);

		if ( ! empty( $description ) ) {
			$setting_data['description'] = $description;
		}

		$this->wpc->add_control(
			new Multimagazine_ColorControl(
				$this->wpc,
				$name,
				$setting_data
			)
		);
	}

	/**
	 * Registers page selection setting
	 *
	 * @param string $name Setting name.
	 * @param string $section Customizer section slug.
	 * @param string $label Control label text.
	 * @param string $description Control description text.
	 */
	public function page_select( $name, $section, $label, $description ) {
		$default = $this->setting_default( $name );
		$choices = array(
			$default => __( 'Select a page', 'multimagazine' ),
		);

		$pages = get_pages();
		foreach ( $pages as $page ) {
			$choices[ $page->ID ] = $page->post_title;
		}

		$this->wpc->add_setting(
			$name,
			array(
				'default'           => $default,
				'sanitize_callback' => 'sanitize_text_field',
			)
		);
		$this->wpc->add_control(
			$name,
			array(
				'label'       => $label,
				'description' => $description,
				'section'     => $section,
				'settings'    => $name,
				'type'        => 'select',
				'choices'     => $choices,
			)
		);
	}

	/**
	 * Registers text setting
	 *
	 * @param String   $name Setting name (slug).
	 * @param String   $section Customizer section in which the setting should appear.
	 * @param String   $label Setting label text.
	 * @param String   $description Setting description text.
	 * @param callable $sanitize_callback Sanitization callback function.
	 */
	public function text_setting( $name, $section, $label, $description = '', $sanitize_callback = 'sanitize_text_field' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'default'           => $this->setting_default( $name ),
				'sanitize_callback' => $sanitize_callback,
			)
		);
		$this->wpc->add_control(
			$name,
			array(
				'label'       => $label,
				'section'     => $section,
				'settings'    => $name,
				'description' => $description,
			)
		);
	}

	/**
	 * Registers text setting
	 *
	 * @param String $name Setting name (slug).
	 * @param String $section Customizer section in which the setting should appear.
	 * @param String $label Setting label text.
	 * @param String $description Setting description text.
	 */
	public function url_setting( $name, $section, $label, $description = '' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'default'           => $this->setting_default( $name ),
				'sanitize_callback' => 'esc_url_raw',
			)
		);
		$this->wpc->add_control(
			$name,
			array(
				'label'       => $label,
				'section'     => $section,
				'settings'    => $name,
				'description' => $description,
				'type'        => 'url',
			)
		);
	}

	/**
	 * Registers number setting
	 *
	 * @param String $name Setting name (slug).
	 * @param String $section Customizer section in which the setting should appear.
	 * @param String $label Setting label text.
	 * @param String $description Setting description text.
	 */
	public function number_setting( $name, $section, $label, $description = '' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'default'           => $this->setting_default( $name ),
				'sanitize_callback' => 'intval',
			)
		);
		$this->wpc->add_control(
			$name,
			array(
				'label'       => $label,
				'section'     => $section,
				'settings'    => $name,
				'description' => $description,
				'type'        => 'number',
			)
		);
	}

	/**
	 * Registers textarea setting
	 *
	 * @param String   $name Setting name (slug).
	 * @param String   $section Customizer section in which the setting should appear.
	 * @param String   $label Setting label text.
	 * @param String   $description Setting description text.
	 * @param callable $sanitize_callback Sanitization callback function.
	 * @param String   $transport Use 'postMessage' value to avoid reloading on change.
	 */
	public function textarea_setting( $name, $section, $label, $description = '', $sanitize_callback = 'sanitize_text_field', $transport = 'refresh' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'sanitize_callback' => $sanitize_callback,
				'default'           => $this->setting_default( $name ),
			)
		);
		$this->wpc->add_control(
			$name,
			array(
				'label'       => $label,
				'section'     => $section,
				'settings'    => $name,
				'type'        => 'textarea',
				'description' => $description,
			)
		);
	}

	/**
	 * Registers an image setting.
	 *
	 * @param String $name Setting name (slug).
	 * @param String $section Customizer section in which the setting should appear.
	 * @param String $label Setting label text.
	 * @param String $description Setting description text.
	 */
	public function image_setting( $name, $section, $label, $description = '' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'sanitize_callback' => array( 'Multimagazine_Sanitizer', 'media' ),
			)
		);
		$this->wpc->add_control(
			new WP_Customize_Image_Control(
				$this->wpc,
				$name,
				array(
					'label'       => $label,
					'section'     => $section,
					'settings'    => $name,
					'description' => $description,
				)
			)
		);
	}

	/**
	 * Registers a cropped image setting.
	 *
	 * @param String $name Setting name (slug).
	 * @param String $section Customizer section in which the setting should appear.
	 * @param String $label Setting label text.
	 * @param String $description Setting description text.
	 */
	public function cropped_image_setting( $name, $section, $label, $description = '' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'sanitize_callback' => array( 'Multimagazine_Sanitizer', 'media' ),
			)
		);
		$this->wpc->add_control(
			new WP_Customize_Cropped_Image_Control(
				$this->wpc,
				$name,
				array(
					'label'       => $label,
					'section'     => $section,
					'settings'    => $name,
					'description' => $description,
					'width'       => 1920,
					'height'      => 1080,
				)
			)
		);
	}

	/**
	 * Registers a media setting.
	 *
	 * @param String $name Setting name (slug).
	 * @param String $section Customizer section in which the setting should appear.
	 * @param String $label Setting label text.
	 * @param String $description Setting description text.
	 */
	public function media_setting( $name, $section, $label, $description = '' ) {
		$this->wpc->add_setting(
			$name,
			array(
				'sanitize_callback' => array( 'Multimagazine_Sanitizer', 'media' ),
			)
		);
		$this->wpc->add_control(
			new WP_Customize_Media_Control(
				$this->wpc,
				$name,
				array(
					'label'       => $label,
					'section'     => $section,
					'settings'    => $name,
					'description' => $description,
				)
			)
		);
	}
}

/*
Custom controls
*/

/**
 * Prints a heading inside customizer panel
 *
 * @param string  $id Element id.
 * @param string  $section Customizer section slug.
 * @param string  $content Title text.
 * @param integer $level Heading level.
 */
function multimagazine_add_heading( $id, $section, $content, $level = 3 ) {
	global $wp_customize;
	$wp_customize->add_setting( $id, array( 'sanitize_callback' => 'sanitize_text_field' ) );
	$wp_customize->add_control(
		new Multimagazine_Customize_Heading(
			$wp_customize,
			$id,
			array(
				'content' => $content,
				'level'   => $level,
				'section' => $section,
			)
		)
	);
}

/**
 * Range control
 *
 * @param string  $section Customizer section slug.
 * @param string  $name Setting name.
 * @param string  $label Control label text.
 * @param integer $default Default value.
 * @param integer $min Minimum possible value.
 * @param integer $max Maximum possible value.
 * @param string  $description Control description text.
 * @param integer $step Step by which the value changes when user clicks the control's arrows.
 * @param string  $transport Use 'postMessage' value to avoid reloading on change.
 */
function multimagazine_register_range_setting( $section, $name, $label, $default, $min = 0, $max = 100, $description = '', $step = 1, $transport = 'refresh' ) {
	global $wp_customize;
	$wp_customize->add_setting(
		$name,
		array(
			'sanitize_callback' => array( 'Multimagazine_Sanitizer', 'number_int' ),
			'default'           => $default,
			'transport'         => $transport,
		)
	);

	$wp_customize->add_control(
		new Multimagazine_Range_Control(
			$wp_customize,
			$name,
			array(
				'min'         => $min,
				'max'         => $max,
				'label'       => $label,
				'description' => $description,
				'section'     => $section,
				'step'        => $step,
				'default'     => $default,
			)
		)
	);
}

/**
 * Select control
 *
 * @param String $name Setting name.
 * @param String $section Customizer section slug.
 * @param String $label Control label text.
 * @param Array  $choices Associative array of choices.
 * @param String $description Control description text.
 * @param String $transport Use 'postMessage' value to avoid reloading on change.
 */
function multimagazine_register_select_setting( $name, $section, $label, $choices, $description = '', $transport = 'refresh' ) {
	global $wp_customize;
	$wp_customize->add_setting(
		$name,
		array(
			'sanitize_callback' => 'sanitize_text_field',
			'default'           => $this->setting_default( $name ),
			'transport'         => $transport,
		)
	);

	$wp_customize->add_control(
		$name,
		array(
			'label'       => $label,
			'section'     => $section,
			'settings'    => $name,
			'type'        => 'select',
			'choices'     => $choices,
			'description' => $description,
		)
	);
}

/**
 * Setting registration functions
 */

/**
 * Registers color setting
 *
 * @param string $name Setting name.
 * @param string $default Default value.
 * @param string $label Control label text.
 * @param string $section Customizer section slug.
 * @param string $description Control description text.
 * @param string $transport Use 'postMessage' value to avoid reloading on change.
 */
function multimagazine_register_color_setting( $name, $default, $label, $section, $description = '', $transport = 'refresh' ) {
	global $wp_customize;
	$wp_customize->add_setting(
		$name,
		array(
			'sanitize_callback' => 'sanitize_hex_color',
			'default'           => $default,
			'transport'         => $transport,
		)
	);
	$setting_data = array(
		'label'    => $label,
		'section'  => $section,
		'settings' => $name,
	);

	if ( ! empty( $description ) ) {
		$setting_data['description'] = $description;
	}
	$wp_customize->add_control(
		new WP_Customize_Color_Control(
			$wp_customize,
			$name,
			$setting_data
		)
	);
}

/**
 * Registers color alpha setting
 *
 * @param string $name Setting name.
 * @param string $default Default value.
 * @param string $label Control label text.
 * @param string $section Customizer section slug.
 * @param string $description Control description text.
 * @param string $transport Use 'postMessage' value to avoid reloading on change.
 */
function multimagazine_register_color_alpha_setting( $name, $default, $label, $section, $description = '', $transport = 'refresh' ) {
	global $wp_customize;
	$wp_customize->add_setting(
		$name,
		array(
			'sanitize_callback' => 'sanitize_text_field',
			'default'           => $default,
			'transport'         => $transport,
		)
	);
	$setting_data = array(
		'label'    => $label,
		'section'  => $section,
		'settings' => $name,
	);

	if ( ! empty( $description ) ) {
		$setting_data['description'] = $description;
	}

	$wp_customize->add_control(
		new Multimagazine_ColorControl(
			$wp_customize,
			$name,
			$setting_data
		)
	);
}

/**
 * Registers checkbox setting
 *
 * @param string  $name Setting name.
 * @param boolean $default Default value.
 * @param string  $label Control label text.
 * @param string  $section Customizer section slug.
 * @param string  $description Control description text.
 */
function multimagazine_register_checkbox_setting( $name, $default, $label, $section, $description = '' ) {
	global $wp_customize;
	$wp_customize->add_setting(
		$name,
		array(
			'sanitize_callback' => array( 'Multimagazine_Sanitizer', 'checkbox' ),
			'default'           => $default,
		)
	);
	$wp_customize->add_control(
		$name,
		array(
			'label'       => $label,
			'section'     => $section,
			'settings'    => $name,
			'type'        => 'checkbox',
			'description' => $description,
		)
	);
}

/**
 * Registers page selection setting
 *
 * @param string $name Setting name.
 * @param string $default Default value.
 * @param string $default_label Default value label.
 * @param string $section Customizer section slug.
 * @param string $label Control label text.
 * @param string $description Control description text.
 * @param object $wp_customize The customizer object.
 */
function multimagazine_register_page_select( $name, $default, $default_label, $section, $label, $description, $wp_customize ) {
	$choices = array(
		$default => $default_label,
	);

	$pages = get_pages();
	foreach ( $pages as $page ) {
		$choices[ $page->ID ] = $page->post_title;
	}

	$wp_customize->add_setting(
		$name,
		array(
			'default'           => $default,
			'sanitize_callback' => 'sanitize_text_field',
		)
	);
	$wp_customize->add_control(
		$name,
		array(
			'label'       => $label,
			'description' => $description,
			'section'     => $section,
			'settings'    => $name,
			'type'        => 'select',
			'choices'     => $choices,
		)
	);
}

/**
 * Registers text setting
 *
 * @param String   $name Setting name (slug).
 * @param String   $section Customizer section in which the setting should appear.
 * @param String   $label Setting label text.
 * @param callable $sanitize_callback Sanitization callback function.
 */
function multimagazine_register_text_setting( $name, $section, $label, $sanitize_callback = 'sanitize_text_field' ) {
	global $wp_customize;

	$wp_customize->add_setting(
		$name,
		array(
			'default'           => $this->setting_default( $name ),
			'sanitize_callback' => $sanitize_callback,
		)
	);
	$wp_customize->add_control(
		$name,
		array(
			'label'    => $label,
			'section'  => $section,
			'settings' => $name,
		)
	);
}

