package com.mindprod.example;

import com.mindprod.common11.BigDate;

import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * How Long until Christmas? computed 8 different ways.
 * <p/>
 * composed with IntelliJ IDEA
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0, 2008-06-21
 */
public final class TestChristmas
    {
    // ------------------------------ FIELDS ------------------------------

    private static final int MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;

    // -------------------------- STATIC METHODS --------------------------

    /**
     * How long till Christmas? ( Sun's way.)
     *
     * @param dayUnitsDiff fractional days till Christmas
     */
    private static void way1( double dayUnitsDiff )
        {
        System.out.println( "1. It is " + dayUnitsDiff
                            + " day units of 24 hours until you may open your presents." );
        }

    /**
     * days till Christmas rounded up.
     *
     * @param dayUnitsDiff fractional days till Christmas
     */
    private static void way2( double dayUnitsDiff )
        {
        //
        System.out.println( "2. It is " + Math.ceil( dayUnitsDiff )
                            + " day units of 24 hours rounded up until you may open your presents." );//
        }

    /**
     * Days till Christmas rounded.
     *
     * @param dayUnitsDiff fractional days till Christmas
     */
    private static void way3( double dayUnitsDiff )
        {
        //
        System.out.println( "3. It is " + Math.round( dayUnitsDiff )
                            + " day units of 24 hours rounded until you may open your presents." );
        }

    /**
     * Days till Christmas rounded down.
     *
     * @param dayUnitsDiff fractional days till Christmas
     */
    private static void way4( double dayUnitsDiff )
        {
        //
        System.out.println( "4. It is " + Math.floor( dayUnitsDiff )
                            + " day units of 24 hours rounded down until you may open your presents." );
        }

    /**
     * relative to Greenwich.
     *
     * @param christmasTimeStamp milliseconds since 1970.
     * @param nowTimeStamp       current time as milliseconds since 1970.
     */
    private static void way5( long christmasTimeStamp, long nowTimeStamp )
        {
        int gmtChristmasOrdinal = ( int ) ( christmasTimeStamp /
                                            MILLISECONDS_PER_DAY );
        int gmtNowOrdinal = ( int ) ( nowTimeStamp / MILLISECONDS_PER_DAY );
        int gmtDiffInDays = gmtChristmasOrdinal - gmtNowOrdinal;
        System.out.println( "5. Children in Greenwich have " +
                            gmtDiffInDays + " sleeps (midnight crossings) to go until\n"
                            + "   you may open your presents.\n"
                            + "   They may open theirs even sooner." );
        }

    /**
     * Time to Christmas measured in sleeps.
     *
     * @param nowCalendar        current time as a GregorianCalendar.
     * @param christmasCalender  nextChristmas as a GregorianCalendar.
     * @param christmasTimeStamp milliseconds since 1970.
     * @param nowTimeStamp       current time as milliseconds since 1970.
     */
    private static void way6( GregorianCalendar nowCalendar, GregorianCalendar christmasCalender, long christmasTimeStamp, long nowTimeStamp )
        {
        // For children living in the USA,
        // the timezone offset will be negative.
        int christmasZoneOffset = christmasCalender.get( Calendar.ZONE_OFFSET ) +
                                  nowCalendar.get( Calendar.DST_OFFSET );
        int localChristmasOrdinal = ( int ) ( ( christmasTimeStamp +
                                                christmasZoneOffset )
                                              / MILLISECONDS_PER_DAY );
        int nowZoneOffset = nowCalendar.get( Calendar.ZONE_OFFSET ) +
                            nowCalendar.get( Calendar.DST_OFFSET );
        int localNowOrdinal = ( int ) ( ( nowTimeStamp + nowZoneOffset ) /
                                        MILLISECONDS_PER_DAY );
        int localDiffInDays = localChristmasOrdinal - localNowOrdinal;
        System.out.println( "6. You have " + localDiffInDays
                            + " sleeps (midnight crossings) to go." );
        }

    /**
     * BigDate Method to compute sleeps till Christmas.
     *
     * @param todayBigDate     local today as a BigDate
     * @param christmasBigDate next Christmas as a BigDate
     */
    private static void way7( BigDate todayBigDate, BigDate christmasBigDate )
        {
        System.out.println( "7. Uncle Roedy's BigDate says it is " +
                            ( christmasBigDate.getOrdinal() - todayBigDate.getOrdinal() )
                            + " sleeps until Christmas." );
        }

    /**
     * Mixed base elapsed time till Christmas.
     *
     * @param todayBigDate     local today as a BigDate
     * @param christmasBigDate next Christmas as a BigDate
     */
    private static void way8( BigDate todayBigDate, BigDate christmasBigDate )
        {
        int[] age = BigDate.age( todayBigDate, christmasBigDate );
        System.out.println( "8. Or put another way " + age[ 0 ]
                            + " years and " + age[ 1 ] + " months and "
                            + age[ 2 ] + " days to go." );
        }

    // --------------------------- main() method ---------------------------

    /**
     * How Long until Christmas?
     *
     * @param args not used
     */
    public static void main( String[] args )
        {
        // Calculate various values needed to compute how long till Christmas.

        final GregorianCalendar nowCalendar = new GregorianCalendar();
        final int thisYear = nowCalendar.get( Calendar.YEAR );
        // You may open presents at 7 AM December 25, local time.
        // This is the instant it time of most interest to children.
        final GregorianCalendar christmasCalendar = new GregorianCalendar( thisYear, Calendar.DECEMBER, 25, 7, 0, 0 );
        // millis since 1970 Jan 1
        final long christmasTimeStamp = christmasCalendar.getTime().getTime();
        final long nowTimeStamp = nowCalendar.getTime().getTime();
        final double dayUnitsDiff = ( christmasTimeStamp - nowTimeStamp ) / ( double ) MILLISECONDS_PER_DAY;
        // The following code will give a negative number just after Christmas.
        final BigDate todayBigDate = BigDate.localToday();
        final BigDate christmasBigDate = new BigDate( todayBigDate.getYYYY(), 12, 25 );

        System.out.println( "Your child asks, how long is it until Christmas?" );
        System.out.println( "Here are the possible answers you might give to an American child:" );
        System.out.println( "You may open your presents at 7 AM Christmas morning." );
        way1( dayUnitsDiff );
        way2( dayUnitsDiff );
        way3( dayUnitsDiff );
        way4( dayUnitsDiff );
        way5( christmasTimeStamp, nowTimeStamp );
        way6( nowCalendar, christmasCalendar, christmasTimeStamp, nowTimeStamp );
        way7( todayBigDate, christmasBigDate );
        way8( todayBigDate, christmasBigDate );
        }
    }