<?php

/**
 * A simple class extending PHP default date time class to recognise all date time patterns across multiple feed types for FeedSync.
 * @since 3.4.5
 * 
 */
class Feedsync_DateTime extends DateTime {


        /**
         * Supported date time formats in feedsync.
         * 'pattern for datetime format'    =>  'date time format compatible with dateTime class'
         */
        public static function fs_get_regex_patterns() {

                $patterns = [
                        '(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})'   =>  'Y-m-d H:i:s',
                        '(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})'   =>  'Y-m-d\TH:i:s',
                        '(\d{4})-(\d{2})-(\d{2})-(\d{2}):(\d{2}):(\d{2})'   =>  'Y-m-d-H:i:s',
                        '(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).(\d{1,6})'   =>  'Y-m-d\TH:i:s.u',
                        '(\d{4})-(\d{2})-(\d{2}) (\d{2})-(\d{2})-(\d{2})'   =>  'Y-m-d H-i-s',
                        '(\d{4})-(\d{2})-(\d{2})-(\d{2})-(\d{2})-(\d{2})'   =>  'Y-m-d-H-i-s',
                        '(\d{4})-(\d{2})-(\d{2})T(\d{2})-(\d{2})-(\d{2})'   =>  'Y-m-d\TH-i-s',
                        '(\d{4})-(\d{2})-(\d{2})'                           =>  'Y-m-d',
                        '(\d{4})(\d{2})(\d{2})-(\d{2}):(\d{2}):(\d{2})'     =>  'Ymd-H:i:s',
                ];

                return $patterns;
        }

        /**
         * Returns the matching dateTime format for input date time string
         */
        public static function fs_get_format_from_datetime($datetime = '') {

                $patterns = self::fs_get_regex_patterns();
                $format = false;

                if (empty($datetime)) {
                        return $format;
                }

                foreach ($patterns as $pattern =>   $pattern_format) {

                        if (preg_match('/^' . $pattern . '$/', $datetime)) {
                                $format = $pattern_format;
                                break;
                        }
                }

                return $format;
        }

        /**
         * Returns the datetime object for date time string.
         * 
         * @param string $datetime
         * @param DateTimeZone|null $timezone Optional timezone of the input datetime string
         * @return DateTime|false
         */
        public static function fs_create_from_format($datetime, DateTimeZone $timezone = null) {

                $format = self::fs_get_format_from_datetime($datetime);

                // Create DateTime with timezone if provided, else default
                if ($timezone) {
                        return DateTime::createFromFormat($format, $datetime, $timezone);
                } else {
                        return DateTime::createFromFormat($format, $datetime);
                }
        }

        public static function fallback($date, $format = 'Y-m-d H:i:s') {

                // supress any timezone related notice/warning;
                error_reporting(0);
                $date_example = '2014-07-22-16:45:56';

                $pos = strpos($date, 'T');

                if ($pos !== false) {
                        $date = new dateTime($date);
                        return $date->format('Y-m-d H:i:s');
                } else {
                        $tempdate = explode('-', $date);
                        $date = $tempdate[0] . '-' . $tempdate[1] . '-' . $tempdate[2];

                        if (isset($tempdate[3])) {
                                $date .= ' ' . $tempdate[3];
                        }

                        return  date($format, strtotime($date));
                }
        }

        public static function fs_convert_format($datetime, $convert_timezone = false, $format = 'Y-m-d H:i:s') {

                $source         = get_option('feedsync_provider_timezone', 'Australia/Melbourne');
                $destination    = get_option('feedsync_timezone', 'Australia/Melbourne');

                // If conversion requested but source and destination are same or destination not set, skip conversion flag
                if (! $convert_timezone || ! $destination || $source === $destination) {
                        $convert_timezone = false;
                }

                $source_tz = null;
                try {
                        if ($source) {
                                $source_tz = new DateTimeZone($source);
                        }
                } catch (Exception $e) {
                        $source_tz = null;
                }

                $date = self::fs_create_from_format($datetime, $source_tz);

                if ($date instanceof DateTime) {

                        if ($convert_timezone) {
                                try {
                                        $date->setTimezone(new DateTimeZone($destination));
                                } catch (Exception $e) {
                                        // Handle invalid destination timezone if necessary
                                }
                        }

                        return $date->format($format);
                } else {
                        return self::fallback($datetime);
                }
        }

        public static function fs_get_current_datetime($convert_timezone = false, $format = 'Y-m-d H:i:s') {

                $source         = get_option('feedsync_provider_timezone', 'Australia/Melbourne');
                $destination    = get_option('feedsync_timezone', 'Australia/Melbourne');

                // If conversion requested but source and destination are same or destination not set, skip conversion flag
                if (! $convert_timezone || ! $destination || $source === $destination) {
                        $convert_timezone = false;
                }

                $source_tz = null;
                try {
                        if ($source) {
                                $source_tz = new DateTimeZone($source);
                        }
                } catch (Exception $e) {
                        $source_tz = null;
                }

                $date = new DateTime('now', $source_tz);

                if ($convert_timezone) {
                        try {
                                $date->setTimezone(new DateTimeZone($destination));
                        } catch (Exception $e) {
                                // Handle invalid destination timezone if necessary
                        }
                }

                return $date->format($format);
        }
}
