<?php
/**
 * Builder CSS Renderer
 *
 * @package Brandy\DynamicCss
 */

namespace Brandy\DynamicCss;

use Brandy\Core\Services\BuilderService;

/**
 * Renders CSS for builder elements
 */
class BuilderCssRenderer {

	/**
	 * Element renderer callback
	 *
	 * @var callable
	 */
	private $element_renderer;

	/**
	 * Constructor
	 *
	 * @param callable $element_renderer Callback to render element variables.
	 */
	public function __construct( callable $element_renderer ) {
		$this->element_renderer = $element_renderer;
	}

	/**
	 * Print styles for given builder
	 *
	 * @param string $builder Builder type (header or footer).
	 * @return void
	 */
	public function print_builder_css( string $builder = 'header' ): void {
		$current_template = brandy_get_builder_template( $builder );

		if ( empty( $current_template ) ) {
			return;
		}

		$all_registered_settings            = BuilderService::get_all_registered_settings();
		$layouts_for_builder_configurations = $all_registered_settings[ $builder ] ?? [];

		if ( isset( $layouts_for_builder_configurations ) ) {
			( $this->element_renderer )(
				[
					'id'       => $builder,
					'settings' => $current_template['settings'],
					'builder'  => $builder,
					'selector' => '#brandy-' . $builder,
				],
				$layouts_for_builder_configurations
			);
		}

		$this->render_placement_elements( $current_template, $builder, $all_registered_settings );
		$this->render_row_configurations( $current_template, $builder, $all_registered_settings );
	}

	/**
	 * Render placement elements
	 *
	 * @param array  $template                Template configuration.
	 * @param string $builder                 Builder type.
	 * @param array  $all_registered_settings All registered settings.
	 * @return void
	 */
	private function render_placement_elements( array $template, string $builder, array $all_registered_settings ): void {
		foreach ( $template['placements'] as $device => $placements ) {
			$available_devices = [ $device ];
			if ( 'mobile' === $device ) {
				$available_devices[] = 'tablet';
			}

			foreach ( $placements as $key => $columns ) {
				if ( 'toggle' === $key ) {
					$this->render_toggle_elements( $columns, $template, $builder, $all_registered_settings, $available_devices );
				} else {
					$this->render_column_elements( $columns, $template, $builder, $all_registered_settings, $available_devices );
				}
			}
		}
	}

	/**
	 * Render toggle elements
	 *
	 * @param array  $element_ids             Element IDs.
	 * @param array  $template                Template configuration.
	 * @param string $builder                 Builder type.
	 * @param array  $all_registered_settings All registered settings.
	 * @param array  $available_devices       Available devices.
	 * @return void
	 */
	private function render_toggle_elements( array $element_ids, array $template, string $builder, array $all_registered_settings, array $available_devices ): void {
		foreach ( $element_ids as $element_id ) {
			$this->render_single_element( $template['elements'][ $element_id ], $builder, $all_registered_settings, $available_devices );
		}
	}

	/**
	 * Render column elements
	 *
	 * @param array  $columns                 Column data.
	 * @param array  $template                Template configuration.
	 * @param string $builder                 Builder type.
	 * @param array  $all_registered_settings All registered settings.
	 * @param array  $available_devices       Available devices.
	 * @return void
	 */
	private function render_column_elements( array $columns, array $template, string $builder, array $all_registered_settings, array $available_devices ): void {
		foreach ( $columns as $col_elements ) {
			foreach ( $col_elements as $element_id ) {
				$this->render_single_element( $template['elements'][ $element_id ], $builder, $all_registered_settings, $available_devices );
			}
		}
	}

	/**
	 * Render a single element
	 *
	 * @param array  $element                 Element configuration.
	 * @param string $builder                 Builder type.
	 * @param array  $all_registered_settings All registered settings.
	 * @param array  $available_devices       Available devices.
	 * @return void
	 */
	private function render_single_element( array $element, string $builder, array $all_registered_settings, array $available_devices ): void {
		$element['builder'] = $builder;
		$cloned_from_id     = $element['cloned_from'] ?? null;
		$checked_id         = isset( $all_registered_settings[ $cloned_from_id ] ) ? $cloned_from_id : $element['id'];

		if ( isset( $all_registered_settings[ $checked_id ] ) ) {
			( $this->element_renderer )( $element, $all_registered_settings[ $checked_id ], $available_devices );
		}
	}

	/**
	 * Render row configurations
	 *
	 * @param array  $template                Template configuration.
	 * @param string $builder                 Builder type.
	 * @param array  $all_registered_settings All registered settings.
	 * @return void
	 */
	private function render_row_configurations( array $template, string $builder, array $all_registered_settings ): void {
		foreach ( $template['row_configurations'] as $row => $data ) {
			$selector = null;
			$id       = ( 'toggle' === $row ) ? 'toggle_off_canvas' : $row . '_' . $builder;

			if ( 'toggle' === $row ) {
				$selector = 'body';
			}

			if ( isset( $all_registered_settings[ $id ] ) ) {
				( $this->element_renderer )(
					[
						'id'       => $id,
						'settings' => $data,
						'builder'  => $builder,
						'selector' => $selector,
					],
					$all_registered_settings[ $id ]
				);
			}
		}
	}
}
