<?php

abstract class SiteOrigin_Widget_Base_Carousel extends SiteOrigin_Widget {
	public $global_settings;

	/**
	 * Register all the frontend scripts and styles for the base carousel.
	 */
	public function initialize() {
		$this->register_frontend_scripts(
			array(
				array(
					'slick',
					plugin_dir_url( SOW_BUNDLE_BASE_FILE ) . 'js/lib/slick' . SOW_BUNDLE_JS_SUFFIX . '.js',
					array( 'jquery' ),
					'1.8.1',
				),
				array(
					'sow-carousel',
					plugin_dir_url( SOW_BUNDLE_BASE_FILE ) . 'js/carousel' . SOW_BUNDLE_JS_SUFFIX . '.js',
					array( 'jquery', 'slick' ),
					SOW_BUNDLE_VERSION,
					true,
				),
			)
		);

		$this->register_frontend_styles(
			array(
				array(
					'slick',
					plugin_dir_url( SOW_BUNDLE_BASE_FILE ) . 'css/lib/slick.css',
					array(),
					'1.8.1',
				),
			)
		);

		add_action( 'wp_enqueue_scripts', array( $this, 'register_assets' ) );
	}

	/**
	 * Allow widgets and other plugins to register assets for this slider.
	 */
	public function register_assets() {
		do_action( 'siteorigin_widgets_carousel_register_assets', $this );
	}

	/**
	 * Allow widgets to override settings.
	 *
	 * @return array If overridden, an array is expected.
	 */
	public function override_carousel_settings() {
		// Intentionally left blank.
		return array();
	}

	/**
	 * Handle carousel specific settings and defaults.
	 *
	 * @return array
	 */
	private function get_carousel_settings() {
		if ( ! empty( $this->global_settings ) ) {
			return $this->global_settings;
		}

		$defaults = array(
			'breakpoints' => array(
				'tablet_landscape' => 1366,
				'tablet_portrait' => 1025,
				'mobile' => 480,
			),
			'slides_to_scroll' => array(
				'desktop' => 3,
				'tablet_landscape' => 3,
				'tablet_portrait' => 2,
				'mobile' => 1,
			),
			'slides_to_show' => array(
				'desktop' => 3,
				'tablet_landscape' => 3,
				'tablet_portrait' => 2,
				'mobile' => 1,
			),
			'navigation' => array(
				'desktop' => true,
				'tablet_landscape' => true,
				'tablet_portrait' => true,
				'mobile' => true,
			),
			'navigation_label' => __( 'Navigation Arrows', 'so-widgets-bundle' ),
			'navigation_dots' => array(
				'desktop' => true,
				'tablet_landscape' => true,
				'tablet_portrait' => true,
				'mobile' => true,
			),
			'navigation_dots_label' => __( 'Navigation Dots', 'so-widgets-bundle' ),
		);

		$this->global_settings = wp_parse_args(
			$this->override_carousel_settings(),
			$defaults
		);

		// If the global settings are somehow empty, return the defaults.
		if ( empty( $this->global_settings ) ) {
			$this->global_settings = $defaults;
		}

		return $this->global_settings;
	}

	/**
	 * Utility method for adding section groups.
	 *
	 * @param array  $field      Field data
	 * @param string $value_type Whether the field is a placeholder or standard field. This controls whether the field data is stored by default.
	 *
	 * @return array The structured section group.
	 */
	private function add_section_group( $field, $value_type ) {
		$carousel_settings = $this->get_carousel_settings();

		$section = array(
			'type' => 'section',
			'label' => $field['label'],
			'hide' => true,
			'fields' => array(),
		);

		if ( isset( $field['fields'] ) ) {
			foreach ( $field['fields'] as $sub_field_key => $sub_field ) {
				$section['fields'][ $sub_field_key ] = $this->add_section_group( $sub_field, $value_type );
			}
		} else {
			if ( isset( $field['breakpoint'] ) ) {
				$section['fields']['breakpoint'] = array(
					'type' => 'number',
					'label' => __( 'Breakpoint', 'so-widgets-bundle' ),
					$value_type => $field['breakpoint'],
				);
			}

			$section['fields']['slides_to_scroll'] = array(
				'type' => 'number',
				'label' => __( 'Slides to Scroll', 'so-widgets-bundle' ),
				'abs' => true,
				'description' => sprintf(
					__( 'Set the number of slides to scroll per navigation click or swipe on %s', 'so-widgets-bundle' ),
					strtolower( $field['label'] )
				),
				$value_type => $field['slides_to_scroll'],
			);

			if ( ! empty( $carousel_settings['slides_to_show'] ) ) {
				$section['fields']['slides_to_show'] = array(
					'type' => 'number',
					'abs' => true,
					'label' => __( 'Slides to Show ', 'so-widgets-bundle' ),
					'description' => sprintf(
						__( 'The number of slides to show on %s.', 'so-widgets-bundle' ),
						strtolower( $field['label'] )
					),
					$value_type => $field['slides_to_show'],
				);
			}

			if ( isset( $field['navigation'] ) && ! empty( $carousel_settings['navigation_label'] ) ) {
				$section['fields']['navigation'] = array(
					'type' => 'checkbox',
					'label' => $carousel_settings['navigation_label'],
					'default' => $field['navigation'],
					'state_handler' => array(
						'nav_arrows[show]' => array( 'show' ),
						'nav_arrows[hide]' => array( 'hide' ),
					),
				);
			}

			if ( isset( $field['navigation_dots'] ) && ! empty( $carousel_settings['navigation_dots_label'] ) ) {
				$section['fields']['navigation_dots'] = array(
					'type' => 'checkbox',
					'label' => $carousel_settings['navigation_dots_label'],
					'default' => $field['navigation'],
					'state_handler' => array(
						'nav_dots[show]' => array( 'show' ),
						'nav_dots[hide]' => array( 'hide' ),
					),
				);
			}
		}

		return $section;
	}

	public function responsive_form_fields( $context = 'widget' ) {
		$carousel_settings = $this->get_carousel_settings();

		// If the context is a widget, the global values are displayed using a
		// placeholder to prevent the values from being stored.
		$value_type = $context == 'widget' ? 'placeholder' : 'default';
		$fields = array(
			'desktop' => array(
				'label' => __( 'Desktop', 'so-widgets-bundle' ),
				'slides_to_scroll' => $carousel_settings['slides_to_scroll']['desktop'],
				'navigation' => $carousel_settings['navigation']['desktop'],
			),
			'tablet' => array(
				'label' => __( 'Tablet', 'so-widgets-bundle' ),
				'fields' => array(
					'landscape' => array(
						'label' => __( 'Landscape', 'so-widgets-bundle' ),
						'breakpoint' => $carousel_settings['breakpoints']['tablet_landscape'],
						'slides_to_scroll' => $carousel_settings['slides_to_scroll']['tablet_landscape'],
						'navigation' => $carousel_settings['navigation']['tablet_landscape'],
					),
					'portrait' => array(
						'label' => __( 'Portrait', 'so-widgets-bundle' ),
						'breakpoint' => $carousel_settings['breakpoints']['tablet_portrait'],
						'slides_to_scroll' => $carousel_settings['slides_to_scroll']['tablet_portrait'],
						'navigation' => $carousel_settings['navigation']['tablet_portrait'],
					),
				),
			),
			'mobile' => array(
				'label' => __( 'Mobile', 'so-widgets-bundle' ),
				'breakpoint' => $carousel_settings['breakpoints']['mobile'],
				'slides_to_scroll' => $carousel_settings['slides_to_scroll']['mobile'],
				'navigation' => $carousel_settings['navigation']['mobile'],
				'navigation_dots' => $carousel_settings['navigation_dots']['mobile'],
			),
		);

		if ( ! empty( $carousel_settings['navigation_dots'] ) ) {
			$fields['desktop']['navigation_dots'] = $carousel_settings['navigation_dots']['desktop'];
			$fields['tablet']['fields']['landscape']['navigation_dots'] = $carousel_settings['navigation_dots']['tablet_landscape'];
			$fields['tablet']['fields']['portrait']['navigation_dots'] = $carousel_settings['navigation_dots']['tablet_portrait'];
			$fields['mobile']['navigation_dots'] = $carousel_settings['navigation_dots']['mobile'];
		}

		// Add slides to show settings if this widget uses them.
		if ( ! empty( $carousel_settings['slides_to_show'] ) ) {
			$fields['desktop']['slides_to_show'] = $carousel_settings['slides_to_show']['desktop'];
			$fields['tablet']['fields']['landscape']['slides_to_show'] = $carousel_settings['slides_to_show']['tablet_landscape'];
			$fields['tablet']['fields']['portrait']['slides_to_show'] = $carousel_settings['slides_to_show']['tablet_portrait'];
			$fields['mobile']['slides_to_show'] = $carousel_settings['slides_to_show']['mobile'];
		}

		$generated_fields = array();

		foreach ( $fields as $field_key => $field ) {
			$generated_fields[ $field_key ] = $this->add_section_group( $field, $value_type );
		}

		return array(
			'type' => 'section',
			'label' => __( 'Responsive', 'so-widgets-bundle' ),
			'hide' => $context == 'widget',
			'fields' => $generated_fields,
		);
	}

	public function carousel_settings_form_fields() {
		$carousel_settings = $this->get_carousel_settings();
		$fields = array(
			'type' => 'section',
			'label' => __( 'Settings', 'so-widgets-bundle' ),
			'hide' => true,
			'fields' => array(
				'loop' => array(
					'type' => 'checkbox',
					'label' => __( 'Loop Items', 'so-widgets-bundle' ),
					'description' => __( 'Automatically return to the first item after the last item.', 'so-widgets-bundle' ),
					'default' => true,
					'state_emitter' => array(
						'callback' => 'conditional',
						'args' => array(
							'loop_posts[show]: val',
							'loop_posts[hide]: ! val',
						),
					),
				),
				'dots' => array(
					'type' => 'checkbox',
					'label' => __( 'Navigation Dots', 'so-widgets-bundle' ),
					'default' => true,
					'state_emitter' => array(
						'callback' => 'conditional',
						'args' => array(
							'nav_dots[show]: val',
							'nav_dots[hide]: ! val',
						),
					),
				),
				'arrows' => array(
					'type' => 'checkbox',
					'label' => __( 'Navigation Arrows', 'so-widgets-bundle' ),
					'default' => true,
					'state_emitter' => array(
						'callback' => 'conditional',
						'args' => array(
							'nav_arrows[show]: val',
							'nav_arrows[hide]: ! val',
						),
					),
				),
				'animation' => array(
					'type' => 'select',
					'label' => __( 'Animation', 'so-widgets-bundle' ),
					'default' => 'Ease',
					'options' => array(
						'ease' => __( 'Ease', 'so-widgets-bundle' ),
						'linear' => __( 'Linear', 'so-widgets-bundle' ),
					),
				),
				'animation_speed' => array(
					'type' => 'number',
					'label' => __( 'Animation Speed', 'so-widgets-bundle' ),
					'default' => 400,
				),
				'autoplay' => array(
					'type' => 'checkbox',
					'label' => __( 'Autoplay', 'so-widgets-bundle' ),
					'state_emitter' => array(
						'callback' => 'conditional',
						'args' => array(
							'autoplay[show]: val',
							'autoplay[hide]: ! val',
						),
					),
				),
				'autoplay_pause_hover' => array(
					'type' => 'checkbox',
					'label' => __( 'Autoplay Pause on Hover', 'so-widgets-bundle' ),
					'state_handler' => array(
						'autoplay[show]' => array( 'show' ),
						'autoplay[hide]' => array( 'hide' ),
					),
				),

				'timeout' => array(
					'type' => 'number',
					'label' => __( 'Timeout', 'so-widgets-bundle' ),
					'default' => 8000,
					'state_handler' => array(
						'autoplay[show]' => array( 'show' ),
						'autoplay[hide]' => array( 'hide' ),
					),
				),
			),
		);

		if ( ! isset( $carousel_settings['navigation'] ) || empty( $carousel_settings['navigation_label'] ) ) {
			unset( $fields['fields']['arrows'] );
		}

		if ( ! isset( $carousel_settings['navigation_dots'] ) || empty( $carousel_settings['navigation_dots_label'] ) ) {
			unset( $fields['fields']['dots'] );
		}

		return $fields;
	}

	public function design_settings_form_fields( $settings = array() ) {
		$fields = array(
			'type' => 'section',
			'label' => __( 'Design', 'so-widgets-bundle' ),
			'hide' => true,
			'fields' => array(
				'item_title' => array(
					'type' => 'section',
					'label' => __( 'Item title', 'so-widgets-bundle' ),
					'hide' => true,
					'fields' => array(
						'tag' => array(
							'type' => 'select',
							'label' => __( 'HTML Tag', 'so-widgets-bundle' ),
							'default' => 'h4',
							'options' => array(
								'h1' => __( 'H1', 'so-widgets-bundle' ),
								'h2' => __( 'H2', 'so-widgets-bundle' ),
								'h3' => __( 'H3', 'so-widgets-bundle' ),
								'h4' => __( 'H4', 'so-widgets-bundle' ),
								'h5' => __( 'H5', 'so-widgets-bundle' ),
								'h6' => __( 'H6', 'so-widgets-bundle' ),
								'p' => __( 'Paragraph', 'so-widgets-bundle' ),
							),
						),
						'font' => array(
							'type' => 'font',
							'label' => __( 'Font', 'so-widgets-bundle' ),
						),
						'size' => array(
							'type' => 'measurement',
							'label' => __( 'Font size', 'so-widgets-bundle' ),
						),
						'color' => array(
							'type' => 'color',
							'label' => __( 'Color', 'so-widgets-bundle' ),
						),
					),
				),
			),
		);

		if ( ! empty( $settings ) ) {
			$fields = array_merge_recursive( $fields, array( 'fields' => $settings ) );
		}

		return $fields;
	}

	public function get_settings_form() {
		return array(
			'responsive' => $this->responsive_form_fields( 'global' ),
		);
	}

	public function responsive_template_variables( $responsive, $encode = true ) {
		$carousel_settings = $this->get_carousel_settings();

		$variables = array(
			'desktop_slides_to_scroll' => ! empty( $responsive['desktop']['slides_to_scroll'] ) ? $responsive['desktop']['slides_to_scroll'] : $carousel_settings['slides_to_scroll']['desktop'],
			'tablet_landscape_breakpoint' => ! empty( $responsive['tablet']['landscape']['breakpoint'] ) ? $responsive['tablet']['landscape']['breakpoint'] : $carousel_settings['breakpoints']['tablet_landscape'],
			'tablet_landscape_slides_to_scroll' => ! empty( $responsive['tablet']['landscape']['slides_to_scroll'] ) ? $responsive['tablet']['landscape']['slides_to_scroll'] : $carousel_settings['slides_to_scroll']['tablet_landscape'],
			'tablet_portrait_breakpoint' => ! empty( $responsive['tablet']['portrait']['breakpoint'] ) ? $responsive['tablet']['portrait']['breakpoint'] : $carousel_settings['breakpoints']['tablet_portrait'],
			'tablet_portrait_slides_to_scroll' => ! empty( $responsive['tablet']['portrait']['slides_to_scroll'] ) ? $responsive['tablet']['portrait']['slides_to_scroll'] : $carousel_settings['slides_to_scroll']['tablet_portrait'],
			'mobile_breakpoint' => ! empty( $responsive['mobile']['breakpoint'] ) ? $responsive['mobile']['breakpoint'] : $carousel_settings['breakpoints']['mobile'],
			'mobile_slides_to_scroll' => ! empty( $responsive['mobile']['slides_to_scroll'] ) ? $responsive['mobile']['slides_to_scroll'] : $carousel_settings['slides_to_scroll']['mobile'],
		);

		if ( ! empty( $carousel_settings['slides_to_show'] ) ) {
			$variables['desktop_slides_to_show'] = ! empty( $responsive['desktop']['slides_to_show'] ) ? $responsive['desktop']['slides_to_show'] : $carousel_settings['slides_to_show']['desktop'];
			$variables['tablet_landscape_slides_to_show'] = ! empty( $responsive['tablet']['landscape']['slides_to_show'] ) ? $responsive['tablet']['landscape']['slides_to_show'] : $carousel_settings['slides_to_show']['tablet_landscape'];
			$variables['tablet_portrait_slides_to_show'] = ! empty( $responsive['tablet']['portrait']['slides_to_show'] ) ? $responsive['tablet']['portrait']['slides_to_show'] : $carousel_settings['slides_to_show']['tablet_portrait'];
			$variables['mobile_slides_to_show'] = ! empty( $responsive['mobile']['slides_to_show'] ) ? $responsive['mobile']['slides_to_show'] : $carousel_settings['slides_to_show']['mobile'];
		}

		// Negative values can be problematic so let's avoid them by ensuring everything is positive.
		$variables = array_map( function( $value ) {
			return is_null( $value ) ? 0 : abs( $value );
		}, $variables );

		return $encode ? json_encode( $variables ) : $variables;
	}

	public function responsive_less_variables( $less_vars, $instance ) {
		$carousel_settings = $this->get_carousel_settings();

		// Breakpoint.
		$less_vars['breakpoint_tablet_landscape'] = ( ! empty( $instance['responsive']['tablet_landscape']['breakpoint'] ) ? $instance['responsive']['tablet_landscape']['breakpoint'] : $carousel_settings['breakpoints']['tablet_landscape'] ) . 'px';
		$less_vars['breakpoint_tablet_portrait'] = ( ! empty( $instance['responsive']['tablet_portrait']['breakpoint'] ) ? $instance['responsive']['tablet_portrait']['breakpoint'] : $carousel_settings['breakpoints']['tablet_portrait'] ) . 'px';
		$less_vars['breakpoint_mobile'] = ( ! empty( $instance['responsive']['mobile']['breakpoint'] ) ? $instance['responsive']['mobile']['breakpoint'] : $carousel_settings['breakpoints']['mobile'] ) . 'px';

		// Navigation.
		$less_vars['navigation_arrows'] = isset( $instance['carousel_settings']['arrows'] ) ? ! empty( $instance['carousel_settings']['arrows'] ) : false;
		$less_vars['navigation_desktop'] = isset( $instance['responsive']['desktop']['navigation'] ) ? ! empty( $instance['responsive']['desktop']['navigation'] ) : $carousel_settings['navigation']['desktop'];
		$less_vars['navigation_tablet_landscape'] = isset( $instance['responsive']['tablet']['landscape']['navigation'] ) ? ! empty( $instance['responsive']['tablet']['landscape']['navigation'] ) : $carousel_settings['navigation']['tablet_landscape'];
		$less_vars['navigation_tablet_portrait'] = isset( $instance['responsive']['tablet']['portrait']['navigation'] ) ? ! empty( $instance['responsive']['tablet']['portrait']['navigation'] ) : $carousel_settings['navigation']['tablet_portrait'];
		$less_vars['navigation_mobile'] = isset( $instance['responsive']['mobile']['navigation'] ) ? ! empty( $instance['responsive']['mobile']['navigation'] ) : $carousel_settings['navigation']['mobile'];

		// Navigation dots.
		$less_vars['navigation_dots_desktop'] = isset( $instance['responsive']['desktop']['navigation_dots'] ) ? ! empty( $instance['responsive']['desktop']['navigation_dots'] ) : $carousel_settings['navigation_dots']['desktop'];
		$less_vars['navigation_dots_tablet_landscape'] = isset( $instance['responsive']['tablet']['landscape']['navigation_dots'] ) ? ! empty( $instance['responsive']['tablet']['landscape']['navigation_dots'] ) : $carousel_settings['navigation_dots']['tablet_landscape'];
		$less_vars['navigation_dots_tablet_portrait'] = isset( $instance['responsive']['tablet']['portrait']['navigation_dots'] ) ? ! empty( $instance['responsive']['tablet']['portrait']['navigation_dots'] ) : $carousel_settings['navigation_dots']['tablet_portrait'];
		$less_vars['navigation_dots_mobile'] = isset( $instance['responsive']['mobile']['navigation_dots'] ) ? ! empty( $instance['responsive']['mobile']['navigation_dots'] ) : $carousel_settings['navigation_dots']['mobile'];

		return $less_vars;
	}

	public function carousel_settings_template_variables( $settings, $encode = true ) {
		$variables = array(
			'loop' => isset( $settings['loop'] ) ? $settings['loop'] : true,
			'dots' => isset( $settings['dots'] ) ? $settings['dots'] : true,
			'animation' => isset( $settings['animation'] ) ? $settings['animation'] : 'ease',
			'animation_speed' => isset( $settings['animation_speed'] ) ? (int) $settings['animation_speed'] : 400,
			'autoplay' => isset( $settings['autoplay'] ) ? $settings['autoplay'] : false,
			'pauseOnHover' => isset( $settings['autoplay_pause_hover'] ) ? $settings['autoplay_pause_hover'] : false,
			'autoplaySpeed' => ! empty( $settings['timeout'] ) ? $settings['timeout'] : 8000,
			'item_overflow' => isset( $settings['item_overflow'] ) ? $settings['item_overflow'] : false,
		);

		return $encode ? json_encode( $variables ) : $variables;
	}

	public function render_template( $settings, $args, $instance ) {
		if (
			! empty( $settings['container_classes'] ) &&
			is_array( $settings['container_classes'] )
		) {
			$container_classes = implode(
				array_map(
					'sanitize_html_class',
					$settings['container_classes']
				)
			);
		}

		include plugin_dir_path( __FILE__ ) . 'tpl/carousel.php';
	}

	public function render_navigation( $nav ) {
		if ( $nav == 'next' || $nav == 'both' ) {
			?>
			<a href="#" class="sow-carousel-next" title="<?php esc_attr_e( 'Next', 'so-widgets-bundle' ); ?>" aria-label="<?php esc_attr_e( 'Next Posts', 'so-widgets-bundle' ); ?>" role="button"></a>
			<?php
		}

		if ( $nav == 'prev' || $nav == 'both' ) {
			?>
			<a href="#" class="sow-carousel-previous" title="<?php esc_attr_e( 'Previous', 'so-widgets-bundle' ); ?>" aria-label="<?php esc_attr_e( 'Previous Posts', 'so-widgets-bundle' ); ?>" role="button"></a>
			<?php
		}
	}
}
