<?php
namespace SabaiApps\Directories\Component\Map\ViewMode;

use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Component\Entity\Type\Query;
use SabaiApps\Directories\Request;
use SabaiApps\Directories\Component\View\Mode\AbstractMode;
use SabaiApps\Directories\Component\Map\FieldType\ICoordinates;

class MapViewMode extends AbstractMode {

	protected function _viewModeInfo() {
		return array(
			'label'             => _x( 'Map', 'view mode label', 'directories-pro' ),
			'default_settings'  => array(
				'template'                => 'map_entities',
				'display'                 => 'summary',
				'filter_only'             => true,
				'map_coordinates_field'   => null,
				'map_color'               => 'primary',
				'map_infobox_width'       => 360,
				'map_height'              => 600,
				'map_marker_icon'         => 'default',
				'map_min_zoom_for_update' => -1,
				'map_debounce_delay'      => 400,
			),
			'default_display'   => 'summary',
			'displays'          => array(
				'summary' => array(
					'label'  => _x( 'Summary', 'display name', 'directories-pro' ),
					'weight' => 1,
				),
			),
			'display_required'  => false,
			'features_disabled' => array(
				'sort',
				'pagination',
				'other' => array( 'add', 'not_found' ),
			),
			'mapable'           => false,
		);
	}

	public function viewModeSupports( Bundle $bundle ) {
		if ( ! parent::viewModeSupports( $bundle )
			|| empty( $bundle->info['public'] )
		) {
			return false;
		}

		foreach ( $this->_application->Entity_Field( $bundle ) as $field ) {
			if ( ! $field_type = $this->_application->Field_Type( $field->getFieldType(), true ) ) {
				continue;
			}

			if ( $field_type instanceof ICoordinates ) {
				return true;
			}
		}
		return false;
	}

	public function viewModeSettingsForm( Bundle $bundle, array $settings, array $parents = array() ) {
		$coordinate_field_options = $this->_application->Entity_Field_options(
			$bundle,
			array(
				'interface'       => 'Map\FieldType\ICoordinates',
				'return_disabled' => true,
			)
		);
		$form                     = array(
			'map_coordinates_field'   => array(
				'#type'             => 'select',
				'#title'            => __( 'Map coordinates field', 'directories-pro' ),
				'#horizontal'       => true,
				'#options'          => $coordinate_field_options[0],
				'#options_disabled' => array_keys( $coordinate_field_options[1] ),
				'#default_value'    => $settings['map_coordinates_field'],
				'#required'         => true,
				'#weight'           => 3,
			),
			'map_color'               => array(
				'#type'             => 'radios',
				'#title'            => __( 'Map color', 'directories-pro' ),
				'#options'          => array( '' => __( 'None', 'directories-pro' ) ) + $this->_application->System_Color_options( array( 'as_background' => true ) ),
				'#option_no_escape' => true,
				'#horizontal'       => true,
				'#default_value'    => $settings['map_color'],
				'#weight'           => 5,
				'#columns'          => 3,
			),
			'map_height'              => array(
				'#type'          => 'slider',
				'#title'         => __( 'Map height', 'directories-pro' ),
				'#default_value' => $settings['map_height'],
				'#min_value'     => 100,
				'#max_value'     => 1000,
				'#step'          => 10,
				'#integer'       => true,
				'#field_suffix'  => 'px',
				'#horizontal'    => true,
				'#weight'        => 10,
			),
			'map_infobox_width'       => array(
				'#type'          => 'slider',
				'#min_value'     => 100,
				'#max_value'     => 500,
				'#step'          => 10,
				'#default_value' => $settings['map_infobox_width'],
				'#title'         => __( 'Map infobox width', 'directories-pro' ),
				'#field_suffix'  => 'px',
				'#integer'       => true,
				'#horizontal'    => true,
				'#weight'        => 21,
			),
			'map_min_zoom_for_update' => array(
				'#type'          => 'slider',
				'#title'         => __( 'Minimum zoom level to load map data', 'directories-pro' ),
				'#description'   => __( 'Set the minimum zoom level at which map data will be loaded. This can help improve performance when displaying a large number of map markers.', 'directories-pro' ),
				'#default_value' => $settings['map_min_zoom_for_update'] ?? -1,
				'#min_value'     => -1,
				'#max_value'     => 20,
				'#min_text'      => __( 'Default', 'directories-pro' ),
				'#step'          => 1,
				'#integer'       => true,
				'#horizontal'    => true,
				'#weight'        => 22,
			),
			'map_debounce_delay'      => array(
				'#type'          => 'slider',
				'#title'         => __( 'Map update debounce delay', 'directories-pro' ),
				'#description'   => __( 'Set the debounce delay (in milliseconds) for map updates when panning or zooming the map.', 'directories-pro' ),
				'#default_value' => $settings['map_debounce_delay'],
				'#min_value'     => 0,
				'#max_value'     => 2000,
				'#step'          => 50,
				'#integer'       => true,
				'#horizontal'    => true,
				'#weight'        => 23,
			),
		);
		$marker_icon_options      = $this->_application->Map_Map_markerIconOptions( $bundle );
		if ( count( $marker_icon_options ) > 1 ) {
			$form['map_marker_icon'] = array(
				'#type'          => 'select',
				'#title'         => __( 'Map marker icon', 'directories-pro' ),
				'#default_value' => $settings['map_marker_icon'],
				'#options'       => $marker_icon_options,
				'#weight'        => 12,
				'#horizontal'    => true,
			);
		}

		return $form;
	}

	public function viewModeOnInitSettings( Bundle $bundle, array &$viewSettings, Request $request ) {
		if ( ! $this->_application->Map_Api() ) {
			$this->_application->logError( 'Map API not configured.' );
			return;
		}

		if ( empty( $viewSettings['view_settings']['map_coordinates_field'] ) ) {
			$this->_application->logError( 'No map coordinates field specified for map view mode.' );
			return;
		}

		$field_name = $viewSettings['view_settings']['map_coordinates_field'];
		if ( ! $this->_application->Entity_Field( $bundle, $field_name ) ) {
			$this->_application->logError( 'Invalid map coordinates field for map view mode: ' . $field_name );
			return;
		}

		$viewSettings['view_settings']['map']                     = $this->_application->getComponent( 'Map' )->getConfig( 'map' );
		$viewSettings['view_settings']['map']['infobox_width']    = $viewSettings['view_settings']['map_infobox_width'];
		$viewSettings['view_settings']['map']['view_marker_icon'] = $viewSettings['view_settings']['map_marker_icon'];
		if ( $viewSettings['view_settings']['map']['default_zoom'] < $viewSettings['view_settings']['map_min_zoom_for_update'] ) {
			$viewSettings['view_settings']['map']['default_zoom'] = $viewSettings['view_settings']['map_min_zoom_for_update'];
		} elseif ( $viewSettings['view_settings']['map_min_zoom_for_update'] < 0 ) {
				$viewSettings['view_settings']['map_min_zoom_for_update'] = $viewSettings['view_settings']['map']['default_zoom'];
		}
		$viewSettings['view_settings']['map']['marker_clusters_max_zoom'] = $viewSettings['view_settings']['map_min_zoom_for_update'] - 1;

		if ( ! $request->isAjax()
			|| ( ! $map_viewport = $request->asStr( 'map_viewport' ) )
			|| ( ! $map_viewport = explode( ',', $map_viewport ) )
			|| count( $map_viewport ) !== 4
		) {
			return;
		}

		$viewSettings['container_template']                      = 'map_entities';
		$viewSettings['view_settings']['skip_render_entities']   = true;
		$viewSettings['view_settings']['filter_only']            = false;
		$viewSettings['view_settings']['map_viewport']           = $map_viewport;
		$viewSettings['view_settings']['map_current_marker_ids'] = ( $ids = $request->asStr( 'map_current_marker_ids' ) ) ? explode( ',', $ids ) : array();
		$viewSettings['view_settings']['map_is_fullscreen']      = $request->asBool( 'map_is_fullscreen', false );
	}

	public function viewModeNav( Bundle $bundle, array $settings ) {
		return array(
			array(
				'margin' => 0,
				'color'  => $color = empty( $settings['map_color'] ) ? null : $settings['map_color'],
				array( array( 'search', 'filter', 'num' ), array(), array( 'map_geolocate', 'map_fullscreen' ) ),
				array( array( 'filters' ) ),
			), // header
			array(
				'margin' => 0,
				'color'  => $color,
				array( array(), array(), array() ),
				array( array(), array(), array() ),
			), // footer
		);
	}

	public function viewModeAssets( Bundle $bundle, array $settings ) {
		$this->_application->Map_Api_load();
		return array(
			'js_files' => array(
				'drts-map-fullmap' => array( 'map-fullmap.min.js', array( 'drts-map-api' ), 'directories-pro', true ),
			),
		);
	}

	public function viewModeOnQuery( Bundle $bundle, Query $query, array $settings ) {
		if ( empty( $settings['map_viewport'] ) ) {
			return;
		}

		$field_name = $settings['map_coordinates_field'];
		$viewport   = $settings['map_viewport'];
		$query->fieldIsOrGreaterThan( $field_name, $viewport[0], 'lat' )
			->fieldIsOrSmallerThan( $field_name, $viewport[2], 'lat' )
			->fieldIsOrGreaterThan( $field_name, $viewport[1], 'lng' )
			->fieldIsOrSmallerThan( $field_name, $viewport[3], 'lng' );
	}
}
