<?php
namespace SabaiApps\Directories\Component\System\Helper;

use SabaiApps\Directories\Application;

/**
 * DateHelper provides methods for formatting and converting dates and times.
 */
class DateHelper {

	/**
	 * Formats a timestamp or date string as a date.
	 *
	 * @param Application $application
	 * @param int|string  $timestamp
	 * @param bool        $html
	 * @param string|null $format
	 * @return string
	 */
	public function help( Application $application, $timestamp, $html = false, $format = null ) {
		if ( is_string( $timestamp )
			&& false === ( $timestamp = $this->strToTime( $application, $timestamp ) )
		) {
			return '';
		}
		return $this->_render( $application, isset( $format ) ? $format : $application->getPlatform()->getDateFormat(), $timestamp, $html );
	}

	/**
	 * Formats a time difference as a time string.
	 *
	 * @param Application $application
	 * @param int         $timediff
	 * @param bool        $html
	 * @param string|null $format
	 * @return string
	 */
	public function time( Application $application, $timediff, $html = false, $format = null ) {
		$timestamp = mktime( 0, 0, 0 ) + $timediff;
		$ret       = date( isset( $format ) ? $format : $application->getPlatform()->getTimeFormat(), $timestamp );
		return $html ? '<time class="drts-datetime">' . $ret . '</time>' : $ret;
	}

	/**
	 * Formats a timestamp or date string as a date and time.
	 *
	 * @param Application       $application
	 * @param int|string        $timestamp
	 * @param bool              $html
	 * @param string|array|null $format
	 * @return string
	 */
	public function datetime( Application $application, $timestamp, $html = false, $format = null ) {
		if ( is_string( $timestamp )
			&& false === ( $timestamp = $this->strToTime( $application, $timestamp ) )
		) {
			return '';
		}

		if ( isset( $format )
			&& ! is_array( $format )
		) {
			$format = array( $format );
		}

		$date_format = isset( $format[0] ) ? $format[0] : $application->getPlatform()->getDateFormat();
		$time_format = isset( $format[1] ) ? $format[1] : $application->getPlatform()->getTimeFormat();

		return $this->_render(
			$application,
			sprintf( _x( '%1$s %2$s', 'date/time format', 'directories-pro' ), $date_format, $time_format ),
			$timestamp,
			$html
		);
	}

	/**
	 * Renders a formatted date/time string, optionally as HTML.
	 *
	 * @param Application $application
	 * @param string      $format
	 * @param int         $timestamp
	 * @param bool        $html
	 * @return string
	 */
	protected function _render( Application $application, $format, $timestamp, $html = false ) {
		$ret = $application->getPlatform()->getDate( $format, $timestamp );
		return $html ? '<time class="drts-datetime" datetime="' . date( 'c', $timestamp ) . '">' . $ret . '</time>' : $ret;
	}

	/**
	 * Checks if the time format is 24-hour.
	 *
	 * @param Application $application
	 * @param string|null $format
	 * @return bool
	 */
	public function is24HourTimeFormat( Application $application, $format = null ) {
		if ( ! isset( $format ) ) {
			$format = $application->getPlatform()->getTimeFormat();
		}
		return strpos( $format, 'H' ) !== false || strpos( $format, 'G' ) !== false;
	}

	/**
	 * Converts a date/time string to a UTC timestamp.
	 *
	 * @param Application $application
	 * @param string      $datetimeStr
	 * @param string      $timezone
	 * @param string|null $format
	 * @return int|false
	 */
	public function strToTime( Application $application, $datetimeStr, $timezone = true, $format = null, $baseTimestamp = null ) {
		if ( ! is_string( $datetimeStr ) ) {
			if ( is_int( $datetimeStr ) ) {
				return $datetimeStr;
			}

			return false;
		}
		if ( ctype_digit( $datetimeStr ) ) {
			return (int) $datetimeStr;
		}

		if ( $timezone === true ) {
			if ( ! $timezone = $application->getPlatform()->getTimeZone() ) {
				$timezone = 'UTC';
			}
		}

		try {
			$tz = new \DateTimeZone( $timezone );

			if ( $format !== null ) {
				$dt = \DateTimeImmutable::createFromFormat( $format, $datetimeStr, $tz );
				if ( ! $dt
					|| ( ( $last_errors = $dt->getLastErrors() ) && ! empty( $last_errors['error_count'] ) )
				) {
					return false;
				}
			} else {
				if ( $baseTimestamp !== null ) {
					$baseDate = ( new \DateTimeImmutable( '@' . $baseTimestamp ) )->setTimezone( $tz );
				} else {
					$baseDate = new \DateTimeImmutable( 'now', $tz );
				}
				$dt = $baseDate->modify( $datetimeStr );
				if ( ! $dt ) {
					return false;
				}
			}

			return $dt->getTimestamp();
		} catch ( \Exception $e ) {
			return false;
		}
	}
}
