<?php

/**
 * @copyright (C) 2013 iJoomla, Inc. - All rights reserved.
 * @license GNU General Public License, version 2 (http://www.gnu.org/licenses/gpl-2.0.html)
 * @author iJoomla.com <webmaster@ijoomla.com>
 * @url https://www.jomsocial.com/license-agreement
 * The PHP code portions are distributed under the GPL license. If not otherwise stated, all images, manuals, cascading style sheets, and included JavaScript *are NOT GPL, and are released under the IJOOMLA Proprietary Use License v1.0
 * More info at https://www.jomsocial.com/license-agreement
 */

use Joomla\CMS\Date\Date;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;

defined('_JEXEC') or die('Restricted access');

require_once JPATH_ROOT . '/components/com_community/libraries/strftime.php';

class CTimeHelper {

    /**
     *
     * @param JDate $date
     *
     */
    public static function timeLapse($date, $showFull = true) {

        $now = Date::getInstance();
        $html = '';
        $diff = CTimeHelper::timeDifference($date->toUnix(), $now->toUnix());


        if (!empty($diff['days'])) {
            $days = $diff['days'];
            $months = ceil($days / 30);

            switch ($days) {
                case ($days == 1):

                    // @rule: Something that happened yesterday
                    $html .= Text::_('COM_COMMUNITY_LAPSED_YESTERDAY');

                    break;
                case ($days > 1 && $days <= 7 && $days < 30):

                    // @rule: Something that happened within the past 7 days
                    $html .= Text::sprintf('COM_COMMUNITY_LAPSED_DAYS', $days) . ' ';

                    break;
                case ($days > 1 && $days > 7 && $days < 30):

                    // @rule: Something that happened within the month but after a week
                    $weeks = round($days / 7);
                    $html .= Text::sprintf(CStringHelper::isPlural($weeks) ? 'COM_COMMUNITY_LAPSED_WEEK_MANY' : 'COM_COMMUNITY_LAPSED_WEEK', $weeks) . ' ';

                    break;
                case ($days >= 30 && $days < 365):

                    // @rule: Something that happened months ago
                    $months = round($days / 30);
                    $html .= Text::sprintf(CStringHelper::isPlural($months) ? 'COM_COMMUNITY_LAPSED_MONTH_MANY' : 'COM_COMMUNITY_LAPSED_MONTH', $months) . ' ';

                    break;
                case ($days > 365):

                    // @rule: Something that happened years ago
                    $years = round($days / 365);
                    $html .= Text::sprintf(CStringHelper::isPlural($years) ? 'COM_COMMUNITY_LAPSED_YEAR_MANY' : 'COM_COMMUNITY_LAPSED_YEAR', $years) . ' ';

                    break;
            }
        } else {
            // We only show he hours if it is less than 1 day
            if (!empty($diff['hours'])) {
                if (!empty($diff['minutes'])) {
                    if ( $diff['hours'] == 1 ) {
                        $html .= Text::sprintf('COM_COMMUNITY_LAPSED_HOUR', $diff['hours']) . ' ';
                    }else {
                        $html .= Text::sprintf('COM_COMMUNITY_LAPSED_HOURS', $diff['hours']) . ' ';
                    }
                } else {
                    $html .= Text::sprintf('COM_COMMUNITY_LAPSED_HOURS_AGO', $diff['hours']) . ' ';
                }
            }

            if (($showFull && !empty($diff['hours'])) || (empty($diff['hours']))) {
                if (!empty($diff['minutes'])) {
                    if ( $diff['minutes'] == 1 ) {
                        $html .= Text::sprintf('COM_COMMUNITY_LAPSED_MINUTE', $diff['minutes']) . ' ';
                    }else {
                        $html .= Text::sprintf('COM_COMMUNITY_LAPSED_MINUTES', $diff['minutes']) . ' ';
                    }
                }

            }
        }

        if (empty($html)) {
            $html .= Text::_('COM_COMMUNITY_LAPSED_LESS_THAN_A_MINUTE');
        }

        return $html;
    }

    /**
     * Function to find time different
     * @param  [type] $start [description]
     * @param  [type] $end   [description]
     * @return [type]        [description]
     */
    static public function timeDifference($start, $end) {
        jimport('joomla.utilities.date');

        if (is_string($start) && ($start != intval($start))) {
            $start = new JDate($start);
            $start = $start->toUnix();
        }

        if (is_string($end) && ($end != intval($end) )) {
            $end = new JDate($end);
            $end = $end->toUnix();
        }

        $uts = array();
        $uts['start'] = $start;
        $uts['end'] = $end;
        if ($uts['start'] !== -1 && $uts['end'] !== -1) {
            if ($uts['end'] >= $uts['start']) {
                $diff = $uts['end'] - $uts['start'];
                if ($days = intval((floor($diff / 86400))))
                    $diff = $diff % 86400;
                if ($hours = intval((floor($diff / 3600))))
                    $diff = $diff % 3600;
                if ($minutes = intval((floor($diff / 60))))
                    $diff = $diff % 60;
                $diff = intval($diff);
                return( array('days' => $days, 'hours' => $hours, 'minutes' => $minutes, 'seconds' => $diff) );
            } else {

                //trigger_error( Text::_("COM_COMMUNITY_TIME_IS_EARLIER_THAN_START_WARNING"), E_USER_WARNING );
            }
        } else {
            trigger_error(Text::_("COM_COMMUNITY_INVALID_DATETIME"), E_USER_WARNING);
        }
        return( false );
    }

    static public function timeIntervalDifference($start, $end) {
        jimport('joomla.utilities.date');


        $start = new JDate($start);
        $start = $start->toUnix();

        $end = new JDate($end);
        $end = $end->toUnix();


        if ($start !== -1 && $end !== -1) {
            return ($start - $end);
        } else {
            trigger_error(Text::_("COM_COMMUNITY_INVALID_DATETIME"), E_USER_WARNING);
        }
        return( false );
    }

    static public function formatTime($jdate) {
        jimport('joomla.utilities.date');
        return CStringHelper::strtolower($jdate->format('%I:%M %p'));
    }

    static public function getInputDate($str = '') {
        require_once( JPATH_ROOT . '/components/com_community/libraries/core.php' );

        $mainframe = Factory::getApplication();
        $config = CFactory::getConfig();

        $timeZoneOffset = $mainframe->get('offset');
        $dstOffset = $config->get('daylightsavingoffset');

        $date = new JDate($str);
        $my = CFactory::getUser();
        $cMy = CFactory::getUser();

        if ($my->id) {
            if (!empty($my->params)) {
                $timeZoneOffset = $my->getParam('timezone', $timeZoneOffset);

                $myParams = $cMy->getParams();
                $dstOffset = $myParams->get('daylightsavingoffset', $dstOffset);
            }
        }

        $timeZoneOffset = (-1) * $timeZoneOffset;
        $dstOffset = (-1) * $dstOffset;
        $date->setTimezone($timeZoneOffset + $dstOffset);

        return $date;
    }

    static public function getDate($str = 'Now', $off = 0) {
        $config = CFactory::getConfig();
        $mainframe = Factory::getApplication();
        $my = CFactory::getUser();
        $cMy = CFactory::getUser();

        $extraOffset = $config->get('daylightsavingoffset');

        $date = new Date($str ?: '');

        $systemOffset = new Date('now', $mainframe->get('offset'));
        $systemOffset = $systemOffset->getOffsetFromGMT(true);

        if (!$my->id) {
            $date->setTimezone(new DateTimeZone(self::getTimezone($systemOffset + $extraOffset)));
        } else {
            if (!empty($my->params)) {
                $pos = CStringHelper::strpos($my->params, 'timezone');
                $offset = $systemOffset + $extraOffset;

                if ($pos === false) {
                    $offset = $systemOffset + $extraOffset;
                } else {
                    $offset = $my->getParam('timezone', -100);
                    $myParams = $cMy->getParams();
                    $myDTS = $myParams->get('daylightsavingoffset');
                    $cOffset = (!empty($myDTS)) ? $myDTS : $config->get('daylightsavingoffset');

                    if ($offset == -100) {
                        $offset = $systemOffset + $extraOffset;
                    } else {
                        $offset = new JDate('now', $offset);
                        $offset = $offset->getOffsetFromGMT(true);
                        
                        $offset = $offset + $cOffset;
                    }
                }

                $date->setTimezone(new DateTimeZone(self::getTimezone($offset)));
            } else
                $date->setTimezone(new DateTimeZone(self::getTimezone($systemOffset + $extraOffset)));
        }

        return $date;
    }

    /**
     * Return locale date
     *
     * @param	null
     * @return	date object
     * @since   2.4.2
     * */
    static public function getLocaleDate($date = 'now') {
        $mainframe = Factory::getApplication();
        $systemOffset = $mainframe->get('offset');

        $now = new Date($date, $systemOffset); // // Joomla 1.6

        $timezone = new DateTimeZone($systemOffset);

        $now->setTimezone($timezone);

        return $now;
    }

    /**
     * Retrieve timezones List.
     *
     * @param string offset
     * @return null|str Timezone.
     * */
    static public function getTimezone($offset) {
       $list = self::getTimezoneList();
       return (isset($list[$offset]))?$list[$offset]:null;
    }

    /**
     * Retrieve timezones List.
     *
     * @param
     * @return	array	The list of timezones available.
     * */
    static public function getTimezoneList() {
        /* Return array */
        $retArray = array();
        /* List all avariable timezone */
        $listTimeZone = DateTimeZone::listIdentifiers(DateTimeZone::ALL);

        /* Check per timezone */
        foreach($listTimeZone as $count => $timeZoneStr){
            /* Get offset from timezone string */
            $dateTimeZone = new DateTimeZone($timeZoneStr);
            $dateTime = new DateTime("now", $dateTimeZone);
            $tmpOffset = $dateTimeZone->getOffset($dateTime);
            $resultOffset = ($tmpOffset < 0?'-':'').abs($tmpOffset)/3600;

            /* Futher concept
            $retArray[$count]['zone'] = '(' . $dateTime->format('P') . ') ' . $timeZoneStr;
            $retArray[$count]['offset'] = $resultOffset;
            */
            $retArray[$resultOffset] = $timeZoneStr;
        }

        return $retArray;
    }

    static public function getOffsetByTimezone($timezone){
        $time = new DateTime('now', new DateTimeZone($timezone));
        $timezoneOffset = ($time->getOffset() < 0?'-':'').abs($time->getOffset())/3600;

        return $timezoneOffset;
    }

    static public function getBeautifyTimezoneList(){
            static $regions = array(
                DateTimeZone::AFRICA,
                DateTimeZone::AMERICA,
                DateTimeZone::ANTARCTICA,
                DateTimeZone::ASIA,
                DateTimeZone::ATLANTIC,
                DateTimeZone::AUSTRALIA,
                DateTimeZone::EUROPE,
                DateTimeZone::INDIAN,
                DateTimeZone::PACIFIC,
            );

            $timezones = array();
            foreach( $regions as $region )
            {
                $timezones = array_merge( $timezones, DateTimeZone::listIdentifiers( $region ) );
            }

            $timezone_offsets = array();
            foreach( $timezones as $timezone )
            {
                $tz = new DateTimeZone($timezone);
                $timezone_offsets[$timezone] = $tz->getOffset(new DateTime("now", $tz));
            }

            // sort timezone by offset
            asort($timezone_offsets);

            $timezone_list = array();
            foreach( $timezone_offsets as $timezone => $offset )
            {
                $offset_prefix = $offset < 0 ? '-' : '+';
                $offset_formatted = gmdate( 'H:i', abs($offset) );

                $pretty_offset = "UTC{$offset_prefix}{$offset_formatted}";

                $timezone_list[$timezone] = "({$pretty_offset}) $timezone";
            }

            return $timezone_list;
    }

    static public function getFormattedTime($time, $format, $offset = 0) {
        $time = strtotime($time);

        // Manually modify the month and day strings in the format.
        if (strpos($format, '%a') !== false) {
            $format = str_replace('%a', CTimeHelper::dayToString(date('w', $time), true), $format);
        }
        if (strpos($format, '%A') !== false) {
            $format = str_replace('%A', CTimeHelper::dayToString(date('w', $time)), $format);
        }
        if (strpos($format, '%b') !== false) {
            $format = str_replace('%b', CTimeHelper::monthToString(date('n', $time), true), $format);
        }
        if (strpos($format, '%B') !== false) {
            $format = str_replace('%B', CTimeHelper::monthToString(date('n', $time)), $format);
        }

        return PHP81_BC\strftime($format, $time);
    }

    /**
     * Translates day of week number to a string.
     *
     * @param	integer	The numeric day of the week.
     * @param	boolean	Return the abreviated day string?
     * @return	string	The day of the week.
     * @since	1.5
     */
    static protected function dayToString($day, $abbr = false) {
        switch ($day) {
            case 0: return $abbr ? Text::_('SUN') : Text::_('SUNDAY');
            case 1: return $abbr ? Text::_('MON') : Text::_('MONDAY');
            case 2: return $abbr ? Text::_('TUE') : Text::_('TUESDAY');
            case 3: return $abbr ? Text::_('WED') : Text::_('WEDNESDAY');
            case 4: return $abbr ? Text::_('THU') : Text::_('THURSDAY');
            case 5: return $abbr ? Text::_('FRI') : Text::_('FRIDAY');
            case 6: return $abbr ? Text::_('SAT') : Text::_('SATURDAY');
        }
    }

    /**
     * Translates month number to a string.
     *
     * @param	integer	The numeric month of the year.
     * @param	boolean	Return the abreviated month string?
     * @return	string	The month of the year.
     * @since	1.5
     */
    static protected function monthToString($month, $abbr = false) {
        switch ($month) {
            case 1: return $abbr ? Text::_('JANUARY_SHORT') : Text::_('JANUARY');
            case 2: return $abbr ? Text::_('FEBRUARY_SHORT') : Text::_('FEBRUARY');
            case 3: return $abbr ? Text::_('MARCH_SHORT') : Text::_('MARCH');
            case 4: return $abbr ? Text::_('APRIL_SHORT') : Text::_('APRIL');
            case 5: return $abbr ? Text::_('MAY_SHORT') : Text::_('MAY');
            case 6: return $abbr ? Text::_('JUNE_SHORT') : Text::_('JUNE');
            case 7: return $abbr ? Text::_('JULY_SHORT') : Text::_('JULY');
            case 8: return $abbr ? Text::_('AUGUST_SHORT') : Text::_('AUGUST');
            case 9: return $abbr ? Text::_('SEPTEMBER_SHORT') : Text::_('SEPTEMBER');
            case 10: return $abbr ? Text::_('OCTOBER_SHORT') : Text::_('OCTOBER');
            case 11: return $abbr ? Text::_('NOVEMBER_SHORT') : Text::_('NOVEMBER');
            case 12: return $abbr ? Text::_('DECEMBER_SHORT') : Text::_('DECEMBER');
        }
    }

    /*
     * Get the exact time from the UTC00:00 time & the offset/timezone given
     * @param   $datetime	datetime is UTC00:00
     * @param   $offset	offset/timezone
     *
     */

    static public function getFormattedUTC($datetime, $offset) {
        $date = new DateTime($datetime);

        $splitTime = explode(".", $offset);
        $begin = new DateTime($datetime);

        // Modify the hour
        $begin->modify($splitTime[0] . ' hour');

        // Modify the minutes
        if (isset($splitTime[1])) {
            // The offset is actually a in 0.x hours. Convert to minute
            $splitTime[1] = $splitTime[1] * 6; // = percentage x 60 minues x 0.1
            $isMinus = ($splitTime[0][0] == '-') ? '-' : '+';
            $begin->modify($isMinus . $splitTime[1] . ' minute');
        }

        return $begin->format('Y-m-d H:i:s');
    }

    static public function convertSQLtimetoChunk($datetime){
        $str = strtotime($datetime);
        $date = array();
        $date['year'] =  date('Y', $str);
        $date['month'] =  date('m', $str);
        $date['day'] =  date('d', $str);
        $date['hour'] =  date('H', $str);
        $date['minute'] =  date('i', $str);
        $date['second'] =  date('s', $str);

        return $date;
    }

}
