/**
 * Copyright (C) 2011 Akiban Technologies Inc.
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 */

package com.akiban.server.encoding;

import org.junit.Test;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;

public class DateTimeEncoderTest {
    private class TestElement {
        private final long asLong;
        private final Object asObject;
        private final String asString;

        public TestElement(String str, Number num) {
            this.asLong = num.longValue();
            this.asObject = num;
            this.asString = str;
        }

        @Override
        public String toString() {
            return String.format("(%d, %s, %s)", asLong, asString, asObject);
        }
    }

    private final LongEncoderBase ENCODER = EncoderFactory.DATETIME;
    
    private final TestElement[] TEST_CASES = {
            new TestElement("0000-00-00 00:00:00", 0),
            new TestElement("1000-01-01 00:00:00", 10000101000000L),
            new TestElement("9999-12-31 23:59:59", 99991231235959L),
            new TestElement("2011-04-10 17:04:03", Long.valueOf(20110410170403L)),
            new TestElement("1986-10-28 05:20:00", BigInteger.valueOf(19861028052000L))
    };

    private String encodeAndDecode(String dateStr) {
        final long val = ENCODER.encodeFromObject(dateStr);
        return ENCODER.decodeToString(val);
    }

    @Test
    public void encodingToInt() {
        for(TestElement t : TEST_CASES) {
            final long encodeFromNum = ENCODER.encodeFromObject(t.asObject);
            final long encodeFromStr = ENCODER.encodeFromObject(t.asString);
            assertEquals("Number->int: " + t, t.asLong, encodeFromNum);
            assertEquals("String->int: " + t, t.asLong, encodeFromStr);
        }
    }

    @Test
    public void decodingToString() {
        for(TestElement t : TEST_CASES) {
            final String decoded = ENCODER.decodeToString(t.asLong);
            assertEquals("int->String: " + t, t.asString, decoded);
        }
    }

    @Test
    public void nullIsZero() {
        assertEquals(0, ENCODER.encodeFromObject(null));
        assertEquals("0000-00-00 00:00:00", ENCODER.decodeToString(0));
    }

    @Test(expected=IllegalArgumentException.class)
    public void datePartNotNumber() {
        encodeAndDecode("2011-01-01zebra 00:00:00");
    }

    @Test(expected=IllegalArgumentException.class)
    public void timePartNotNumber() {
        encodeAndDecode("2011-01-01 00:00:00zebra");
    }

    @Test(expected=IllegalArgumentException.class)
    public void partialDatePart() {
        encodeAndDecode("2011-01 00:00:00");
    }

    @Test(expected=IllegalArgumentException.class)
    public void partialTimePart() {
        encodeAndDecode("2011-01-01 00:00");
    }

    @Test(expected=IllegalArgumentException.class)
    public void noNumbers() {
        encodeAndDecode("zebra");
    }

    @Test(expected=IllegalArgumentException.class)
    public void tooManyDateParts() {
        encodeAndDecode("2000-01-01-01 00:00:00");
    }

    @Test(expected=IllegalArgumentException.class)
    public void tooManyTimeParts() {
        encodeAndDecode("2000-01-01 00:00:00:00");
    }

    @Test(expected=IllegalArgumentException.class)
    public void onlyDatePart() {
        encodeAndDecode("2000-01-01");
    }

    @Test(expected=IllegalArgumentException.class)
    public void onlyTimePart() {
        encodeAndDecode("10:11:12");
    }
}

@@ -710,17 +710,16 @@
 t.Test;%0A
-%0A
 import j
@@ -744,600 +744,120 @@
 r;%0A%0A
-import static org.junit.Assert.assertEquals;%0A%0Apublic class DateTimeEncoderTest %7B%0A    private class TestElement %7B%0A        private final long asLong;%0A        private final Object asObject;%0A        private final String asString;%0A%0A        public TestElement(String str, Number num) %7B%0A            this.asLong = num.longValue();%0A            this.asObject = num;%0A            this.asString = str;%0A        %7D%0A%0A        @Override%0A        public String toString() %7B%0A            return String.format(%22(%25d, %25s, %25s)%22, asLong, asString, asObject);%0A        %7D%0A    %7D%0A%0A    private final LongEncoderBase ENCODER = 
+public class DateTimeEncoderTest extends LongEncoderTestBase %7B%0A    public DateTimeEncoderTest() %7B%0A        super(
 Enco
@@ -879,32 +879,27 @@
 TIME
-;
+,
 %0A    
-%0A
     
-private final
+      new
  Tes
@@ -913,23 +913,14 @@
 t%5B%5D 
-TEST_CASES = %7B%0A
+%7B%0A    
     
@@ -970,16 +970,20 @@
 0%22, 0),%0A
+    
         
@@ -1047,32 +1047,36 @@
 L),%0A            
+ 
+   
 new TestElement(
@@ -1120,32 +1120,36 @@
 L),%0A            
+   
+ 
 new TestElement(
@@ -1203,16 +1203,20 @@
 403L)),%0A
+    
         
@@ -1303,995 +1303,32 @@
     
-%7D;%0A%0A    private String encodeAndDecode(String dateStr) %7B%0A        final long val = ENCODER.encodeFromObject(dateStr);%0A        return ENCODER.decodeToString(val);%0A    %7D%0A%0A    @Test%0A    public void encodingToInt() %7B%0A        for(TestElement t : TEST_CASES) %7B%0A            final long encodeFromNum = ENCODER.encodeFromObject(t.asObject);%0A            final long encodeFromStr = ENCODER.encodeFromObject(t.asString);%0A            assertEquals(%22Number-%3Eint: %22 + t, t.asLong, encodeFromNum);%0A            assertEquals(%22String-%3Eint: %22 + t, t.asLong, encodeFromStr);%0A        %7D%0A    %7D%0A%0A    @Test%0A    public void decodingToString() %7B%0A        for(TestElement t : TEST_CASES) %7B%0A            final String decoded = ENCODER.decodeToString(t.asLong);%0A            assertEquals(%22int-%3EString: %22 + t, t.asString, decoded);%0A        %7D%0A    %7D%0A%0A    @Test%0A    public void nullIsZero() %7B%0A        assertEquals(0, ENCODER.encodeFromObject(null));%0A        assertEquals(%220000-00-00 00:00:00%22, ENCODER.decodeToString(0));%0A    %7D
+          %7D);%0A    %7D%0A    
 %0A%0A  

Refactor DateTimeEncoderTest to use LongEncoderTestBase.