// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gwtorm.protobuf;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import com.google.gwtorm.client.Column;
import com.google.gwtorm.data.Address;
import com.google.gwtorm.data.Person;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;

import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

public class ProtobufEncoderTest {
  private static final byte[] testingBin = new byte[] {
  //
      // name
      0x0a, 0x09,
      // name.name
      0x0a, 0x07, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, //
      // age
      0x10, (byte) 75, //
      // registered (true)
      0x18, 0x01 //
      //
      };

  @SuppressWarnings("cast")
  @Test
  public void testPerson() throws UnsupportedEncodingException {
    final ProtobufCodec<Person> e = CodecFactory.encoder(Person.class);

    Person p = e.decode(testingBin);
    assertNotNull(p);
    assertTrue(p instanceof Person);
    assertEquals("testing", p.name());
    assertEquals(75, p.age());
    assertTrue(p.isRegistered());

    final byte[] out = e.encodeToByteArray(p);
    assertEquals(asString(testingBin), asString(out));
    assertEquals(testingBin.length, e.sizeof(p));
  }

  @Test
  public void testAddress() {
    final ProtobufCodec<Address> e =
        CodecFactory.encoder(Address.class);
    Address a = e.decode(new byte[0]);
    assertNotNull(a);
    assertNull(a.location());

    Person.Key k = new Person.Key("bob");
    @SuppressWarnings("unused")
    Person p = new Person(k, 42);
    Address b = new Address(new Address.Key(k, "ny"), "ny");

    byte[] act = e.encodeToByteArray(b);

    Address c = e.decode(act);
    assertEquals(c.location(), b.location());
    assertEquals(c.city(), b.city());
    assertEquals(c.key(), b.key());
  }

  @Test
  public void testDecodeEmptiesByteBuffer() {
    ProtobufCodec<Person> e = CodecFactory.encoder(Person.class);
    ByteBuffer buf = ByteBuffer.wrap(testingBin);
    @SuppressWarnings("unused")
    Person p = e.decode(buf);
    assertEquals(0, buf.remaining());
    assertEquals(testingBin.length, buf.position());
  }

  @Test
  public void testEncodeFillsByteBuffer() throws UnsupportedEncodingException {
    ProtobufCodec<Person> e = CodecFactory.encoder(Person.class);

    Person p = new Person(new Person.Key("testing"), 75);
    p.register();

    int sz = e.sizeof(p);
    assertEquals(testingBin.length, sz);

    ByteBuffer buf = ByteBuffer.allocate(sz);
    e.encode(p, buf);
    assertEquals(0, buf.remaining());
    assertEquals(sz, buf.position());

    buf.flip();
    byte[] act = new byte[sz];
    buf.get(act);

    assertEquals(asString(testingBin), asString(act));
  }

  @Test
  public void testEncodeNonArrayByteBuffer()
      throws UnsupportedEncodingException {
    ProtobufCodec<Person> e = CodecFactory.encoder(Person.class);

    Person p = new Person(new Person.Key("testing"), 75);
    p.register();

    int sz = e.sizeof(p);
    assertEquals(testingBin.length, sz);

    ByteBuffer buf = ByteBuffer.allocateDirect(sz);
    assertFalse("direct ByteBuffer has no array", buf.hasArray());

    e.encode(p, buf);
    assertEquals(0, buf.remaining());
    assertEquals(sz, buf.position());

    buf.flip();
    byte[] act = new byte[sz];
    buf.get(act);

    assertEquals(asString(testingBin), asString(act));
  }

  @Test
  public void testStringList() throws UnsupportedEncodingException {
    ProtobufCodec<StringList> e = CodecFactory.encoder(StringList.class);

    StringList list = new StringList();
    list.list = new ArrayList<String>();
    list.list.add("moe");
    list.list.add("larry");

    byte[] act = e.encodeToByteArray(list);
    StringList other = e.decode(act);
    assertNotNull(other.list);
    assertEquals(list.list, other.list);
    assertEquals(asString(new byte[] { //
        //
            0x12, 0x03, 'm', 'o', 'e', //
            0x12, 0x05, 'l', 'a', 'r', 'r', 'y' //
        }), asString(act));
  }

  @Test
  public void testStringSet() throws UnsupportedEncodingException {
    ProtobufCodec<StringSet> e = CodecFactory.encoder(StringSet.class);

    StringSet list = new StringSet();
    list.list = new TreeSet<String>();
    list.list.add("larry");
    list.list.add("moe");

    byte[] act = e.encodeToByteArray(list);
    StringSet other = e.decode(act);
    assertNotNull(other.list);
    assertEquals(list.list, other.list);
    assertEquals(asString(new byte[] { //
        //
            0x0a, 0x05, 'l', 'a', 'r', 'r', 'y', //
            0x0a, 0x03, 'm', 'o', 'e' //
        }), asString(act));
  }

  @Test
  public void testPersonList() {
    ProtobufCodec<PersonList> e = CodecFactory.encoder(PersonList.class);

    PersonList list = new PersonList();
    list.people = new ArrayList<Person>();
    list.people.add(new Person(new Person.Key("larry"), 1 << 16));
    list.people.add(new Person(new Person.Key("curly"), 1));
    list.people.add(new Person(new Person.Key("moe"), -1));

    PersonList other = e.decode(e.encodeToByteArray(list));
    assertNotNull(other.people);
    assertEquals(list.people, other.people);
  }

  @Test
  public void testCustomEncoderList() {
    ProtobufCodec<ItemList> e = CodecFactory.encoder(ItemList.class);

    ItemList list = new ItemList();
    list.list = new ArrayList<Item>();
    list.list.add(new Item());
    list.list.add(new Item());

    ItemList other = e.decode(e.encodeToByteArray(list));
    assertNotNull(other.list);
    assertEquals(2, other.list.size());
  }

  @Test
  public void testEnumEncoder() throws UnsupportedEncodingException {
    assertEquals(1, ThingWithEnum.Type.B.ordinal());
    assertSame(ThingWithEnum.Type.B, ThingWithEnum.Type.values()[1]);

    ProtobufCodec<ThingWithEnum> e = CodecFactory.encoder(ThingWithEnum.class);

    ThingWithEnum thing = new ThingWithEnum();
    thing.type = ThingWithEnum.Type.B;

    ThingWithEnum other = e.decode(e.encodeToByteArray(thing));
    assertNotNull(other.type);
    assertSame(thing.type, other.type);

    byte[] act = e.encodeToByteArray(thing);
    byte[] exp = {0x08, 0x01};
    assertEquals(asString(exp), asString(act));
  }

  @Test
  public void testEncodeToStream()throws IOException {
    ProtobufCodec<ThingWithEnum> e = CodecFactory.encoder(ThingWithEnum.class);

    ThingWithEnum thing = new ThingWithEnum();
    thing.type = ThingWithEnum.Type.B;

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    e.encodeWithSize(thing, out);
    byte[] exp = {0x02, 0x08, 0x01};
    assertEquals(asString(exp), asString(out.toByteArray()));

    byte[] exp2 = {0x02, 0x08, 0x01, '\n'};
    ByteArrayInputStream in = new ByteArrayInputStream(exp2);
    ThingWithEnum other = e.decodeWithSize(in);
    assertTrue('\n' == in.read());
    assertTrue(-1 == in.read());
    assertNotNull(other.type);
    assertSame(thing.type, other.type);
  }

  private static String asString(byte[] bin)
      throws UnsupportedEncodingException {
    return new String(bin, "ISO-8859-1");
  }

  static class PersonList {
    @Column(id = 5)
    public List<Person> people;
  }

  static class StringList {
    @Column(id = 2)
    List<String> list;
  }

  static class StringSet {
    @Column(id = 1)
    SortedSet<String> list;
  }

  static class Item {
  }

  static class ItemCodec extends ProtobufCodec<Item> {
    @Override
    public void encode(Item obj, CodedOutputStream out) throws IOException {
      out.writeBoolNoTag(true);
    }

    @Override
    public void mergeFrom(CodedInputStream in, Item obj) throws IOException {
      in.readBool();
    }

    @Override
    public Item newInstance() {
      return new Item();
    }

    @Override
    public int sizeof(Item obj) {
      return 1;
    }
  }

  static class ItemList {
    @Column(id = 2)
    @CustomCodec(ItemCodec.class)
    List<Item> list;
  }

  static class ThingWithEnum {
    static enum Type {
      A, B;
    }

    @Column(id = 1)
    Type type;
  }
}
