<?php

class PhonalisaDate
{

    const StandardDateTimeZone = 'UTC';
    const TimePatternWithoutSeconds = 'H:i';
    const TimePatternWithSeconds = 'H:i:s';
    const TimePatternWithMeridiem = 'h:i a';
    const ServertimePatternWithSeconds = 'Y-m-d H:i:s';
    const ServertimePatternWithOutSeconds = 'Y-m-d H:i';

    public static function newServerDate(
    $dateString = null, $pattern = PhonalisaDate::ServertimePatternWithSeconds
    )
    {
        $serverTimeZone = new DateTimeZone(PhonalisaDate::StandardDateTimeZone);
        if ($dateString == null || $dateString == "") {
            $date = new DateTime('now', $serverTimeZone); // date from timestamp
            return $date->format(PhonalisaDate::ServertimePatternWithSeconds);
        }

        $date = DateTime::createFromFormat($pattern, $dateString, PhonalisaDate::userTimeZone());
        if (!$date) {
            //"Can not create new date please check your date format."
            throw new CHttpException(400, __("PHONALISA_DATE_CAN_NOT_CREATE_NEW_SERVER_DATE"));
        }

        $date->setTimezone($serverTimeZone);
        return $date->format(PhonalisaDate::ServertimePatternWithSeconds);
    }

    public static function convertServerDateTo(
    $pattern, $dateString = null, $toUserTimeZone = false
    )
    {
        $serverTimeZone = new DateTimeZone(PhonalisaDate::StandardDateTimeZone);
        if (!$dateString) {
            $dateString = PhonalisaDate::newServerDate();
        }
        $date = DateTime::createFromFormat(PhonalisaDate::ServertimePatternWithSeconds, $dateString, $serverTimeZone);

        // Sometimes the date is set without the seconds (e.g. Birthday in addresses model), if $date is not set correcty try it without the seconds...
        if (!$date) {
            $date = DateTime::createFromFormat(PhonalisaDate::ServertimePatternWithOutSeconds, $dateString, $serverTimeZone);
        }

        if (!$date) {
            throw new CHttpException(400, __("PHONALISA_DATE_CAN_CONVERT_DATE"));
        }
        if ($toUserTimeZone) {
            $date->setTimezone(PhonalisaDate::userTimeZone());
        }
        return PhonalisaDate::dateToFormat($date, $pattern);
    }

    public static function newServerTimestamp()
    {
        $serverTimeZone = new DateTimeZone(PhonalisaDate::StandardDateTimeZone);
        $date = new DateTime('now', $serverTimeZone);
        return $date->format('U');
    }

    public static function userDate($dateString)
    {
        $date = PhonalisaDate::dateFromServerFormat($dateString);
        return PhonalisaDate::dateToFormat($date, PhonalisaDate::userDatePattern());
    }

    public static function userTime($dateString, $withSeconds = false)
    {
        $date = PhonalisaDate::dateFromServerFormat($dateString);
        return PhonalisaDate::dateToFormat($date, PhonalisaDate::userTimePattern($withSeconds));
    }

    public static function userDateTime($dateString, $withSeconds = false)
    {
        $userDate = PhonalisaDate::userDate($dateString);
        $userTime = PhonalisaDate::userTime($dateString, $withSeconds);
        return $userDate . ' ' . $userTime;
    }
    /* Return time in custom format */

    public static function dateToFormat($date, $format)
    {
        if (!$date) {
            return;
        }
        return $date->format($format);
    }

    public static function dateFromServerFormat($dateString)
    {
        $serverTimeZone = new DateTimeZone(PhonalisaDate::StandardDateTimeZone);
        $userTimeZone = PhonalisaDate::userTimeZone();
        $newDate = null;

        if (is_int($dateString)) {
            $newDate = DateTime::createFromFormat('U', $dateString, $serverTimeZone); // date from timestamp
        } else {
            $newDate = DateTime::createFromFormat(PhonalisaDate::ServertimePatternWithSeconds, $dateString, $serverTimeZone);
        }

        if (!$newDate) {
            return;
        }
        $newDate->setTimezone($userTimeZone);
        return $newDate;
    }

    public static function userTimeZone($useRealUser = false)
    {
        $user = app()->user->sudoUserInstance;
        if ($useRealUser) {
            $user = app()->user->realUserInstance;
        }
        $timeZoneString = cfg('TIMEZONE');
        if ($user && $user->user_timezone) {
            $timeZoneString = $user->user_timezone;
        }
        $timeZone = new DateTimeZone($timeZoneString);
        return $timeZone;
    }

    public static function useMeridianTimeFormat($useRealUser = false)
    {
        $user = app()->user->sudoUserInstance;
        if ($useRealUser) {
            $user = app()->user->realUserInstance;
        }
        $timePattern = cfg('USER_TIME_FORMAT');
        if ($user && $user->user_time_format) {
            $timePattern = $user->user_time_format;
        }
        return $timePattern == '12';
    }

    public static function userDatePattern($useRealUser = false)
    {
        $user = app()->user->sudoUserInstance;
        if ($useRealUser) {
            $user = app()->user->realUserInstance;
        }
        $datePattern = cfg('USER_DATE_FORMAT');
        if ($user && $user->user_date_format) {
            $datePattern = $user->user_date_format;
        }
        return PhonalisaDate::yiiToPhpPattern($datePattern);
    }

    public static function userTimePattern($withSeconds = false, $useRealUser = false)
    {
        if ($withSeconds) {
            return PhonalisaDate::useMeridianTimeFormat($useRealUser) ? 'h:i:s a' : 'H:i:s';
        } else {
            return PhonalisaDate::useMeridianTimeFormat($useRealUser) ? 'h:i a' : 'H:i';
        }
    }

    public static function yiiToPhpPattern($yiiPattern)
    {
        $search = array('yyyy', 'MM', 'dd', 'hh', 'HH', 'mm');
        $replace = array('Y', 'm', 'd', 'g', 'h', 'i');
        $phpPattern = str_replace($search, $replace, $yiiPattern);
        return $phpPattern;
    }

    public static function getUserTimeZoneOffset($useRealUser = false, $displayFormat = 'O')
    {
        $userTimeZone = self::userTimeZone($useRealUser);
        $dateTime = new DateTime("now", $userTimeZone);
        return $dateTime->format($displayFormat);
    }

    public static function changeRFC2822EnglishToUserLanguage($date = null, $translate = true)
    {
        $rfc2822 = PhonalisaDate::convertServerDateTo(DateTime::RFC2822, $date, true);

        if ($translate === true) {
            $searchMonths = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
            $searchDays = array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');

            $replaceMonths = Yii::app()->locale->getMonthNames('abbreviated', true);
            $replaceDays = Yii::app()->locale->getWeekDayNames('abbreviated', true);

            $rfc2822 = str_replace($searchDays, $replaceDays, $rfc2822);
            $rfc2822 = str_replace($searchMonths, $replaceMonths, $rfc2822);
        }
        return $rfc2822;
    }

    public static function changeSearchRequestDateTimeToServerFormat($dateTime, $dateTimeFormat)
    {
        $userTimezone = PhonalisaDate::userTimeZone();
        $serverTimezone = new DateTimeZone(PhonalisaDate::StandardDateTimeZone);
        $date = new DateTime($dateTime, $userTimezone);
        $date->setTimezone($serverTimezone);
        return PhonalisaDate::dateToFormat($date, $dateTimeFormat);
    }
}
