/*
 * [TestChristmas.java]
 *
 * Summary: How Long until Christmas? computed 8 different ways.
 *
 * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
 *
 * Licence: This software may be copied and used freely for any purpose but military.
 *          http://mindprod.com/contact/nonmil.html
 *
 * Requires: JDK 1.8+
 *
 * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
 *
 * Version History:
 *  1.0 2008-06-21
 */
package com.mindprod.example;

import com.mindprod.common18.BigDate;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;

import static java.lang.System.*;

/**
 * How Long until Christmas? computed 8 different ways.
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0 2008-06-21
 * @since 2008-06-21
 */
public final class TestChristmas
    {
    /**
     * How long till Christmas? ( Sun's way.)
     *
     * @param dayUnitsDiff fractional days till Christmas
     */
    private static void way1( double dayUnitsDiff )
        {
        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 )
        {
        //
        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 )
        {
        //
        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 )
        {
        //
        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 ) TimeUnit.MILLISECONDS.toDays( christmasTimeStamp );
        int gmtNowOrdinal = ( int ) TimeUnit.MILLISECONDS.toDays( nowTimeStamp );
        int gmtDiffInDays = gmtChristmasOrdinal - gmtNowOrdinal;
        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 ) TimeUnit.MILLISECONDS.toDays( christmasTimeStamp +
                                                                          christmasZoneOffset );
        int nowZoneOffset = nowCalendar.get( Calendar.ZONE_OFFSET ) +
                            nowCalendar.get( Calendar.DST_OFFSET );
        int localNowOrdinal = ( int ) TimeUnit.MILLISECONDS.toDays( nowTimeStamp + nowZoneOffset );
        int localDiffInDays = localChristmasOrdinal - localNowOrdinal;
        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 )
        {
        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 );
        out.println( "8. Or put another way " + age[ 0 ]
                     + " years and " + age[ 1 ] + " months and "
                     + age[ 2 ] + " days to go." );
        }

    /**
     * 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-01-01
        final long christmasTimeStamp = christmasCalendar.getTime().getTime();
        final long nowTimeStamp = nowCalendar.getTime().getTime();
        final double dayUnitsDiff = ( christmasTimeStamp - nowTimeStamp ) / ( double ) TimeUnit.DAYS.toMillis( 1 );
        // 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 );
        out.println( "Your child asks, how long is it until Christmas?" );
        out.println( "Here are the possible answers you might give to an American child:" );
        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 );
        }
    }