package de.duehl.basics.datetime;

/*
 * Copyright 2016 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import static org.junit.Assert.*;

import java.util.Calendar;
import java.util.regex.Pattern;

import org.junit.Test;

import de.duehl.basics.datetime.date.DateHelper;
import de.duehl.basics.datetime.date.ImmutualDate;
import de.duehl.basics.datetime.time.ImmutualTime;
import de.duehl.basics.datetime.time.TimeHelper;

public class TimestampTest {

    @Test
    public void compareTimeStamps1() {
        String timeStamp1 = "20140604_150927";
        String timeStamp2 = "20140604_150928";

        assertTrue(Timestamp.compareTimestamps(timeStamp1, timeStamp2) < 0);
    }

    @Test
    public void compareTimeStamps2() {
        String timeStamp1 = "20140604_150927";

        assertTrue(Timestamp.compareTimestamps(timeStamp1, timeStamp1) == 0);
    }

    @Test
    public void compareTimeStamps3() {
        String timeStamp1 = "20140604_150927";
        String timeStamp2 = "20140604_150928";

        assertTrue(Timestamp.compareTimestamps(timeStamp2, timeStamp1) > 0);
    }

    @Test
    public void compareTimeStamps4() {
        String timeStamp1 = "20140603_150928";
        String timeStamp2 = "20140604_150928";

        assertTrue(Timestamp.compareTimestamps(timeStamp1, timeStamp2) < 0);
    }

    @Test
    public void firstTimestampIsNewer1() {
        String timeStamp1 = "20140603_150928";
        String timeStamp2 = "20140604_150928";

        assertEquals(false,
                Timestamp.firstTimestampIsNewer(timeStamp1, timeStamp2));
    }

    @Test
    public void firstTimestampIsNewer2() {
        String timeStamp1 = "20140604_150928";

        assertEquals(false,
                Timestamp.firstTimestampIsNewer(timeStamp1, timeStamp1));
    }

    @Test
    public void firstTimestampIsNewer3() {
        String timeStamp1 = "20140604_150928";
        String timeStamp2 = "20140603_150928";

        assertEquals(true,
                Timestamp.firstTimestampIsNewer(timeStamp1, timeStamp2));
    }

    @Test
    public void firstTimestampIsNewer4() {
        String timeStamp1 = "20140604_150928";
        String timeStamp2 = "20140604_150927";

        assertEquals(true,
                Timestamp.firstTimestampIsNewer(timeStamp1, timeStamp2));
    }

    @Test
    public void firstTimestampIsOlder1() {
        String timeStamp1 = "20140604_150928";
        String timeStamp2 = "20140603_150928";

        assertEquals(false,
                Timestamp.firstTimestampIsOlder(timeStamp1, timeStamp2));
    }

    @Test
    public void firstTimestampIsOlder2() {
        String timeStamp1 = "20140604_150928";

        assertEquals(false,
                Timestamp.firstTimestampIsOlder(timeStamp1, timeStamp1));
    }

    @Test
    public void firstTimestampIsOlder3() {
        String timeStamp1 = "20140603_150928";
        String timeStamp2 = "20140604_150928";

        assertEquals(true,
                Timestamp.firstTimestampIsOlder(timeStamp1, timeStamp2));
    }

    @Test
    public void firstTimestampIsOlder4() {
        String timeStamp1 = "20140604_150927";
        String timeStamp2 = "20140604_150928";

        assertEquals(true,
                Timestamp.firstTimestampIsOlder(timeStamp1, timeStamp2));
    }

    @Test
    public void switchDateTimePartInNameWithExchange() {
        String front = "c:/temp/blabla_";
        String timestamp = "20160314_150113";
        String rear = "_foo_bar_baz.txt";
        String logFile = front + timestamp + rear;
        String exchange = "huhu";
        String expected = front + exchange + rear;
        String actual = Timestamp.switchDateTimePartInName(logFile, exchange);
        assertEquals(expected, actual);
    }

    @Test (expected = RuntimeException.class)
    public void switchDateTimePartInNameWithoutPattern() {
        String front = "c:/temp/blabla_";
        String timestamp = "20160314_###_150113"; // falsch!
        String rear = "_foo_bar_baz.txt";
        String logFile = front + timestamp + rear;
        String exchange = "huhu";
        Timestamp.switchDateTimePartInName(logFile, exchange);
    }

    @Test
    public void switchDateTimePartInNameWithoutExchange() {
        String front = "c:/temp/blabla_";
        String timestamp = "20160314_150113";
        String rear = "_foo_bar_baz.txt";
        String logFile = front + timestamp + rear;

        String log = Timestamp.switchDateTimePartInName(logFile);
        assertTrue(log.startsWith(front));
        assertTrue(log.endsWith(rear));
        assertTrue(log.matches(Pattern.quote(front) + "\\d{8}_\\d{6}" + Pattern.quote(rear)));
    }

    @Test (expected = RuntimeException.class)
    public void switchDateTimePartInNameWithoutPatternWithoutExchange() {
        String front = "c:/temp/blabla_";
        String timestamp = "20160314_###_150113"; // falsch!
        String rear = "_foo_bar_baz.txt";
        String logFile = front + timestamp + rear;
        Timestamp.switchDateTimePartInName(logFile);
    }

    @Test
    public void beautifyTimeStamp01() {
        String timeStamp = "20140604_150927";
        String actual = Timestamp.beautifyTimestamp(timeStamp);
        String expected = "04.06.2014, 15:09:27";

        assertEquals(expected, actual);
    }

    @Test
    public void beautifyTimeStampNotCorrectInput() {
        String timeStamp = "foo";
        String actual = Timestamp.beautifyTimestamp(timeStamp);
        String expected = "foo";

        assertEquals(expected, actual);
    }

    @Test
    public void beautifiedTimestampToFullTimestamp01() {
        String beautifiedTimestamp = "04.06.2014, 15:09:27";
        String actual = Timestamp.beautifiedTimestampToFullTimestamp(beautifiedTimestamp);
        String expected = "20140604_150927";

        assertEquals(expected, actual);
    }

    @Test
    public void beautifiedTimestampToFullTimestamp02() {
        String timeStamp = "20170315_121932";
        String beautifiedTimestamp = Timestamp.beautifyTimestamp(timeStamp);
        String actual = Timestamp.beautifiedTimestampToFullTimestamp(beautifiedTimestamp);
        String expected = timeStamp;

        assertEquals(expected, actual);
    }

    @Test
    public void beautifiedTimestampToFullTimestampNotCorrectInput() {
        String beautifiedTimestamp = "foo";
        String actual = Timestamp.beautifiedTimestampToFullTimestamp(beautifiedTimestamp);
        String expected = "foo";

        assertEquals(expected, actual);
    }

    @Test (expected = IllegalArgumentException.class)
    public void getDateFromTimestampOnWrongInput() {
        String timestamp = "foo_20140604_150927";
        Timestamp.getDateFromTimestamp(timestamp);
    }

    @Test (expected = IllegalArgumentException.class)
    public void getDateFromTimestampOnEmptyInput() {
        String timestamp = "";
        Timestamp.getDateFromTimestamp(timestamp);
    }

    @Test
    public void getDateFromTimestamp() {
        String timestamp = "20140604_150927";
        ImmutualDate date = Timestamp.getDateFromTimestamp(timestamp);

        int actualYear = date.getYear();
        int actualMonth = date.getMonth();
        int actualDay = date.getDay();

        int expectedYear = 2014;
        int expectedMonth = 6;
        int expectedDay = 4;

        assertEquals(expectedYear, actualYear);
        assertEquals(expectedMonth, actualMonth);
        assertEquals(expectedDay, actualDay);
    }

    @Test (expected = IllegalArgumentException.class)
    public void getTimeFromTimestampOnWrongInput() {
        String timestamp = "foo_20140604_150927";
        Timestamp.getTimeFromTimestamp(timestamp);
    }

    @Test (expected = IllegalArgumentException.class)
    public void getTimeFromTimestampOnEmptyInput() {
        String timestamp = "";
        Timestamp.getTimeFromTimestamp(timestamp);
    }

    @Test
    public void getTimeFromTimestamp() {
        String timestamp = "20140604_150927";
        ImmutualTime time = Timestamp.getTimeFromTimestamp(timestamp);

        int actualHours = time.getHour();
        int actualMinutes = time.getMinute();
        int actualSeconds = time.getSecond();

        int expectedHours = 15;
        int expectedMinutes = 9;
        int expectedSeconds = 27;

        assertEquals(expectedHours, actualHours);
        assertEquals(expectedMinutes, actualMinutes);
        assertEquals(expectedSeconds, actualSeconds);
    }

    @Test
    public void getDateAndTimeFromTimestamp() {
        String timestamp = "20140604_150927";
        DateAndTime dateAndTime = Timestamp.getDateAndTimeFromTimestamp(timestamp);

        ImmutualDate date = Timestamp.getDateFromTimestamp(timestamp);

        int actualYear = date.getYear();
        int actualMonth = date.getMonth();
        int actualDay = date.getDay();

        int expectedYear = 2014;
        int expectedMonth = 6;
        int expectedDay = 4;

        assertEquals(expectedYear, actualYear);
        assertEquals(expectedMonth, actualMonth);
        assertEquals(expectedDay, actualDay);


        ImmutualTime time = dateAndTime.getTime();

        int actualHours = time.getHour();
        int actualMinutes = time.getMinute();
        int actualSeconds = time.getSecond();

        int expectedHours = 15;
        int expectedMinutes = 9;
        int expectedSeconds = 27;

        assertEquals(expectedHours, actualHours);
        assertEquals(expectedMinutes, actualMinutes);
        assertEquals(expectedSeconds, actualSeconds);
    }



    @Test
    public void actualDate() {
        String actualDate = Timestamp.actualDate();
        assertEquals(10, actualDate.length());
    }

    @Test
    public void actualTime() {
        String actualTime = Timestamp.actualTime();
        assertEquals(8, actualTime.length());
    }

    @Test
    public void actualDateAgainstCalendar() {
        Calendar cal = Calendar.getInstance();
        String expectedDate = String.format("%02d.%02d.%04d",
                cal.get(Calendar.DAY_OF_MONTH),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.YEAR));

        String actualDate = DateHelper.actualDateAsString();

        assertEquals(expectedDate, actualDate);
    }

    @Test
    public void actualTimeAgainstCalendar() {
        Calendar cal = Calendar.getInstance();
        ImmutualTime time = TimeHelper.actualTime();

        String expectedTime = String.format("%02d:%02d:%02d",
                cal.get(Calendar.HOUR_OF_DAY),
                cal.get(Calendar.MINUTE),
                cal.get(Calendar.SECOND));

        String actualTime = time.toString();

        assertEquals(expectedTime, actualTime);
        /*
         * Kann durchaus schief gehen, wenn zwischen
         *     Calendar.getInstance()
         * und
         *     TimeHelper.actualTime()
         * die Sekunde wechselt.
         */
    }

    @Test
    public void actualDateAndTimeAgainstCalendar() {
        String delimiter = "###";

        Calendar cal = Calendar.getInstance();
        DateAndTime now = new DateAndTime();
        ImmutualTime time = now.getTime();
        String actualTime = time.toString();
        ImmutualDate date = now.getDate();
        String actualDate = date.toString();

        String expected = String.format("%02d.%02d.%04d%s%02d:%02d:%02d",
                cal.get(Calendar.DAY_OF_MONTH),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.YEAR),
                delimiter,
                cal.get(Calendar.HOUR_OF_DAY),
                cal.get(Calendar.MINUTE),
                cal.get(Calendar.SECOND));
        String actual = actualDate + delimiter + actualTime;
        assertEquals(expected, actual);
        /*
         * Kann durchaus schief gehen, wenn zwischen
         *     Calendar.getInstance()
         * und
         *     TimeHelper.actualTime()
         * die Sekunde wechselt.
         */
    }

    @Test
    public void actualDateAgainstCalendarRealTest() {
        Calendar cal = Calendar.getInstance();
        String expectedDate = String.format("%02d.%02d.%04d",
                cal.get(Calendar.DAY_OF_MONTH),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.YEAR));

        String actualDate = Timestamp.actualDate();

        assertEquals(expectedDate, actualDate);
    }

    @Test
    public void actualTimeAgainstCalendarRealTest() {
        Calendar cal = Calendar.getInstance();
        String actualTime = Timestamp.actualTime();

        String expectedTime = String.format("%02d:%02d:%02d",
                cal.get(Calendar.HOUR_OF_DAY),
                cal.get(Calendar.MINUTE),
                cal.get(Calendar.SECOND));

        assertEquals(expectedTime, actualTime);
        /*
         * Kann durchaus schief gehen, wenn zwischen
         *     Calendar.getInstance()
         * und
         *     Timestamp.actualTime()
         * die Sekunde wechselt.
         */
    }

    @Test
    public void actualDateAndTimeAgainstCalendarRealTest() {
        String delimiter = "###";

        Calendar cal = Calendar.getInstance();
        String actualTime = Timestamp.actualTime();
        String actualDate = Timestamp.actualDate();

        String expected = String.format("%02d.%02d.%04d%s%02d:%02d:%02d",
                cal.get(Calendar.DAY_OF_MONTH),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.YEAR),
                delimiter,
                cal.get(Calendar.HOUR_OF_DAY),
                cal.get(Calendar.MINUTE),
                cal.get(Calendar.SECOND));

        String actual = actualDate + delimiter + actualTime;

        assertEquals(expected, actual);
        /*
         * Kann durchaus schief gehen, wenn zwischen
         *     Calendar.getInstance()
         * und
         *     Timestamp.actualTime()
         * die Sekunde wechselt.
         */
    }

    @Test
    public void fullTimestampAgainstCalendarTest() {
        String delimiter = "###";

        Calendar cal = Calendar.getInstance();
        DateAndTime now = new DateAndTime();
        ImmutualTime time = now.getTime();
        String actualTime = time.asHhMmSs();
        ImmutualDate date = now.getDate();
        String actualDate = date.asYyyyMmDd();

        String expected = String.format("%04d%02d%02d%s%02d%02d%02d",
                cal.get(Calendar.YEAR),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.DAY_OF_MONTH),
                delimiter,
                cal.get(Calendar.HOUR_OF_DAY),
                cal.get(Calendar.MINUTE),
                cal.get(Calendar.SECOND));
        String actual = actualDate + delimiter + actualTime;
        assertEquals(expected, actual);
        /*
         * Kann durchaus schief gehen, wenn zwischen
         *     Calendar.getInstance()
         * und
         *     TimeHelper.actualTime()
         * die Sekunde wechselt.
         */
    }

    @Test
    public void fullTimestampAgainstCalendarTestRealTest() {
        String delimiter = "###";

        Calendar cal = Calendar.getInstance();
        String actual = Timestamp.fullTimestamp(delimiter);

        String expected = String.format("%04d%02d%02d%s%02d%02d%02d",
                cal.get(Calendar.YEAR),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.DAY_OF_MONTH),
                delimiter,
                cal.get(Calendar.HOUR_OF_DAY),
                cal.get(Calendar.MINUTE),
                cal.get(Calendar.SECOND));

        assertEquals(expected, actual);
        /*
         * Kann durchaus schief gehen, wenn zwischen
         *     Calendar.getInstance()
         * und
         *     Timestamp.fullTimestamp()
         * die Sekunde wechselt.
         */
    }

    @Test
    public void isTimestampOk() {
        String timestamp = "20140604_150927";
        assertTrue(Timestamp.isTimestamp(timestamp));
    }

    @Test
    public void isTimestampFailWrongDelimiter() {
        String timestamp = "20140604-150927";
        assertFalse(Timestamp.isTimestamp(timestamp));
    }

    @Test
    public void isTimestampFailMissingDelimiter() {
        String timestamp = "20140604150927";
        assertFalse(Timestamp.isTimestamp(timestamp));
    }

    @Test
    public void isTimestampFailMissingNumberFront() {
        String timestamp = "2014060_150927";
        assertFalse(Timestamp.isTimestamp(timestamp));
    }

    @Test
    public void isTimestampFailMissingNumberRear() {
        String timestamp = "20140604_15092";
        assertFalse(Timestamp.isTimestamp(timestamp));
    }

    @Test
    public void isTimestampFailToMuchNumbers() {
        String timestamp = "000020140604_1509270000";
        assertFalse(Timestamp.isTimestamp(timestamp));
    }

}
