<?php

namespace SugarCalendarBookings\Locations;

use SugarCalendarBookings\Services\ServiceModel;

/**
 * Online location.
 *
 * @since 1.0.0
 */
class OnlineLocation extends AbstractLocation {

	/**
	 * The location UID.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	private $uid;

	/**
	 * The location provider.
	 *
	 * @since 1.0.0
	 *
	 * @var AbstractOnlineLocationProvider
	 */
	private $provider;

	/**
	 * The location order.
	 *
	 * Only needed in the Service context.
	 *
	 * @since 1.0.0
	 *
	 * @var int|null
	 */
	private $order;

	/**
	 * The service ID.
	 *
	 * Online locations is local per service.
	 *
	 * @since 1.0.0
	 *
	 * @var int
	 */
	private $service_id;

	/**
	 * Constructor.
	 *
	 * @since 1.0.0
	 *
	 * @param string                         $uid      The location UID.
	 * @param AbstractOnlineLocationProvider $provider The location provider.
	 * @param int                            $order    The location order.
	 */
	public function __construct( $uid, $provider, $order = null ) {

		$this->uid        = $uid;
		$this->provider   = $provider;
		$this->order      = $order;
		$this->service_id = (int) explode( ':', $this->uid )[0];
	}

	/**
	 * Get the location type.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function get_type() {

		return 'online';
	}

	/**
	 * Get the location UID.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function get_uid() {

		return $this->uid;
	}

	/**
	 * Get the location provider.
	 *
	 * @since 1.0.0
	 *
	 * @return AbstractOnlineLocationProvider
	 */
	public function get_provider() {

		return $this->provider;
	}

	/**
	 * Get the location order.
	 *
	 * @since 1.0.0
	 *
	 * @return int
	 */
	public function get_order() {

		return $this->order ?? 0;
	}

	/**
	 * Get the location display name.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function get_display_name() {

		return $this->provider->get_display_name();
	}

	/**
	 * Get the location address.
	 *
	 * @since 1.0.0
	 *
	 * @return null|string
	 */
	public function get_address() {

		return null;
	}

	/**
	 * Get the service ID.
	 *
	 * @since 1.0.0
	 *
	 * @return int
	 */
	public function get_service_id() {

		return $this->service_id;
	}

	/**
	 * Get a location by UID.
	 *
	 * @since 1.0.0
	 *
	 * @param string $uid The location UID.
	 *
	 * @return OnlineLocation|null
	 */
	public static function get( $uid ) {

		$service_id = explode( ':', $uid )[0];

		$service = ServiceModel::get( $service_id );

		if ( ! $service ) {
			return null;
		}

		foreach ( $service->online_locations as $online_location ) {
			if ( $online_location['uid'] === $uid ) {
				return self::from_array( $online_location );
			}
		}

		return null;
	}

	/**
	 * Create an online location from an array.
	 *
	 * @since 1.0.0
	 *
	 * @param array $data The location data.
	 *
	 * @return OnlineLocation|null
	 */
	public static function from_array( $data ) {

		if ( ! isset( $data['uid'] ) ) {
			return null;
		}

		$provider = OnlineLocationProviderFactory::from_array( $data );

		if ( ! $provider ) {
			return null;
		}

		$order = isset( $data['order'] ) ? (int) $data['order'] : null;

		return new OnlineLocation( $data['uid'], $provider, $order );
	}

	/**
	 * Convert the location to an array.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	public function to_array() {

		$data = array_merge(
			[
				'uid' => $this->uid,
			],
			$this->provider->to_array()
		);

		if ( $this->order !== null ) {
			$data['order'] = $this->order;
		}

		return $data;
	}
}
