/**
 * 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.ais.metamodel.io;

import com.akiban.ais.model.AkibanInformationSchema;
import com.akiban.ais.model.Group;
import com.akiban.ais.model.GroupIndex;
import com.akiban.ais.model.IndexColumn;
import com.akiban.ais.model.Table;
import com.akiban.ais.model.aisb2.AISBBasedBuilder;
import com.akiban.ais.model.aisb2.NewAISBuilder;
import com.akiban.server.rowdata.SchemaFactory;
import org.junit.Test;

import java.nio.ByteBuffer;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;

public final class MessageTest {
    private static AkibanInformationSchema coiSchema() throws Exception {
        SchemaFactory schemaFactory = new SchemaFactory("test");
        return schemaFactory.ais("create table test.c(id int key, name varchar(32)) engine=akibandb;",
                                 "create table test.o(id int key, cid int, foo int, "+
                                 "constraint __akiban foreign key(cid) references c(id)) engine=akibandb;",
                                 "create table test.i(id int key, oid int, "+
                                 "constraint __akiban foreign key(oid) references o(id)) engine=akibandb;");
    }

    private static void serializeAndCompare(AkibanInformationSchema ais) throws Exception {
        ByteBuffer buffer = ByteBuffer.allocate(1 << 19);
        new Writer(new MessageTarget(buffer)).save(ais);
        buffer.flip();
        AkibanInformationSchema newAis = new Reader(new MessageSource(buffer)).load();
        assertEquals("buffer left", 0, buffer.remaining());
        assertEquals("groups", ais.getGroups().keySet(), newAis.getGroups().keySet());
        assertEquals("user tables", ais.getUserTables().keySet(), newAis.getUserTables().keySet());
        assertEquals("group tables", ais.getGroupTables().keySet(), newAis.getGroupTables().keySet());
        assertEquals("joins", ais.getJoins().keySet(), newAis.getJoins().keySet());
        newAis.checkIntegrity();
    }

    @Test
    public void emptyAIS() throws Exception {
        AkibanInformationSchema ais = new AkibanInformationSchema();
        serializeAndCompare(ais);
    }

    @Test
    public void coiAIS() throws Exception {
        AkibanInformationSchema ais = coiSchema();
        serializeAndCompare(ais);
    }

    @Test
    public void coiAISWithGroupIndex() throws Exception {
        final AkibanInformationSchema ais = coiSchema();
        final Table cTable = ais.getTable("test", "c");
        assertNotNull("c table not null", cTable);
        final Table oTable = ais.getTable("test", "o");
        assertNotNull("o table not null", oTable);
        final Group group = cTable.getGroup();
        assertSame("customer and order group", group, oTable.getGroup());
        final GroupIndex fooIndex = GroupIndex.create(ais, group, "foo", 100, false, "KEY", null);
        fooIndex.addColumn(new IndexColumn(fooIndex, cTable.getColumn("name"), 0, true, null));
        fooIndex.addColumn(new IndexColumn(fooIndex, oTable.getColumn("foo"), 1, true, null));
        ais.checkIntegrity();
        serializeAndCompare(ais);
    }

    @Test
    public void unicodeSchemaAndTableNames() throws Exception {
        NewAISBuilder builder = AISBBasedBuilder.create();
        AkibanInformationSchema ais =
            builder
            .userTable("test", "☃").colLong("id").pk("id")
            .userTable("☂", "rain").colLong("id").pk("id")
            .userTable("☾", "☽").colLong("id").pk("id")
            .ais();
        serializeAndCompare(ais);
    }
}

@@ -1315,16 +1315,38 @@
 iSchema(
+boolean withGroupIndex
 ) throws
@@ -1350,32 +1350,32 @@
 ows Exception %7B%0A
-
         SchemaFa
@@ -1480,24 +1480,41 @@
 st.c(id int 
+not null primary 
 key, name va
@@ -1523,32 +1523,16 @@
 har(32))
- engine=akibandb
 ;%22,%0A    
@@ -1584,24 +1584,41 @@
 st.o(id int 
+not null primary 
 key, cid int
@@ -1625,25 +1625,25 @@
 , foo int, %22
-+
+,
 %0A           
@@ -1665,35 +1665,24 @@
        %22
-constraint __akiban
+grouping
  foreign
@@ -1708,32 +1708,16 @@
 s c(id))
- engine=akibandb
 ;%22,%0A    
@@ -1773,16 +1773,33 @@
 (id int 
+not null primary 
 key, oid
@@ -1809,9 +1809,9 @@
 t, %22
-+
+,
 %0A   
@@ -1845,27 +1845,16 @@
    %22
-constraint __akiban
+grouping
  for
@@ -1888,25 +1888,121 @@
 id))
- engine=akibandb;
+;%22,%0A                                 withGroupIndex ? %22create index foo on o(c.name, o.foo) using left join;%22 : %22
 %22);%0A
@@ -3059,32 +3059,37 @@
 ais = coiSchema(
+false
 );%0A        seria
@@ -3234,24 +3234,28 @@
 = coiSchema(
+true
 );%0A        f
@@ -3502,24 +3502,24 @@
 getGroup();%0A
+
         asse
@@ -3584,298 +3584,8 @@
 ));%0A
-        final GroupIndex fooIndex = GroupIndex.create(ais, group, %22foo%22, 100, false, %22KEY%22, null);%0A        fooIndex.addColumn(new IndexColumn(fooIndex, cTable.getColumn(%22name%22), 0, true, null));%0A        fooIndex.addColumn(new IndexColumn(fooIndex, oTable.getColumn(%22foo%22), 1, true, null));%0A
     

Fix MessageTest ddl