// Copyright 2010 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.nosql;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.google.gwtorm.data.Person;
import com.google.gwtorm.data.PhoneBookDb;
import com.google.gwtorm.schema.QueryModel;
import com.google.gwtorm.schema.RelationModel;
import com.google.gwtorm.schema.java.JavaSchemaModel;
import com.google.gwtorm.server.GeneratedClassLoader;
import com.google.gwtorm.server.OrmException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

@SuppressWarnings("unchecked")
public class IndexFunctionTest {
  private JavaSchemaModel schema;
  private RelationModel people;

  @Before
  public void setUp() throws Exception {
    schema = new JavaSchemaModel(PhoneBookDb.class);
    people = schema.getRelation("people");
  }

  @Test
  public void testPersonByName() throws Exception {
    IndexFunction<Person> idx = index("testMyQuery", "WHERE name=?");
    Assert.assertEquals("testMyQuery", idx.getName());

    IndexKeyBuilder b;
    Person p;

    b = new IndexKeyBuilder();
    p = new Person(new Person.Key("bob"), 12);
    assertTrue(idx.includes(p));
    idx.encode(b, p);
    assertEqualToBuilderResult(new byte[] {'b', 'o', 'b'}, b);
  }

  @Test
  public void testPersonByNameAge() throws Exception {
    IndexFunction<Person> idx = index("nameAge", "WHERE name=? AND age=?");
    Assert.assertEquals("nameAge", idx.getName());

    IndexKeyBuilder b;
    Person p;

    b = new IndexKeyBuilder();
    p = new Person(new Person.Key("hm"), 42);
    assertTrue(idx.includes(p));
    idx.encode(b, p);
    assertEqualToBuilderResult(new byte[] {'h', 'm', 0x00, 0x01, 0x01, 42}, b);

    p = new Person(new Person.Key(null), 0);
    assertFalse(idx.includes(p));
  }

  @Test
  public void testPersonByNameAge_OrderByName() throws Exception {
    IndexFunction<Person> idx = index("nameAge", "WHERE name=? AND age=? ORDER BY name");
    Assert.assertEquals("nameAge", idx.getName());

    IndexKeyBuilder b;
    Person p;

    b = new IndexKeyBuilder();
    p = new Person(new Person.Key("qy"), 42);
    assertTrue(idx.includes(p));
    idx.encode(b, p);
    assertEqualToBuilderResult(new byte[] {'q', 'y', 0x00, 0x01, 0x01, 42}, b);
  }

  @Test
  public void testPersonByNameAge_OrderByRegistered() throws Exception {
    IndexFunction<Person> idx = index("nameAge", "WHERE name=? AND age=? ORDER BY registered");
    Assert.assertEquals("nameAge", idx.getName());

    IndexKeyBuilder b;
    Person p;

    b = new IndexKeyBuilder();
    p = new Person(new Person.Key("q"), 42);
    p.register();
    assertTrue(idx.includes(p));
    idx.encode(b, p);
    assertEqualToBuilderResult(
        new byte[] {
          'q',
          0x00,
          0x01, // name
          0x01,
          42,
          0x00,
          0x01, // age
          0x01,
          0x01 // registered
        },
        b);
  }

  @Test
  public void testPersonByNameRange_OrderByName() throws Exception {
    IndexFunction<Person> idx = index("nameSuggest", "WHERE name >= ? AND name <= ? ORDER BY name");
    assertEquals("nameSuggest", idx.getName());

    IndexKeyBuilder b;
    Person p;

    b = new IndexKeyBuilder();
    p = new Person(new Person.Key("q"), 42);
    assertTrue(idx.includes(p));
    idx.encode(b, p);
    assertEqualToBuilderResult(new byte[] {'q'}, b);
  }

  @Test
  public void testOnlyRegistered() throws Exception {
    IndexFunction<Person> idx = index("isregistered", "WHERE registered = true ORDER BY name");
    assertEquals("isregistered", idx.getName());

    IndexKeyBuilder b;
    Person p;

    b = new IndexKeyBuilder();
    p = new Person(new Person.Key("q"), 42);
    assertFalse(idx.includes(p));
    p.register();
    assertTrue(idx.includes(p));

    idx.encode(b, p);
    assertEqualToBuilderResult(new byte[] {'q'}, b);
  }

  @Test
  public void testOnlyAge42() throws Exception {
    IndexFunction<Person> idx = index("isOldEnough", "WHERE age = 42 ORDER BY name");
    assertEquals("isOldEnough", idx.getName());

    IndexKeyBuilder b;
    Person p;

    b = new IndexKeyBuilder();
    p = new Person(new Person.Key("q"), 32);
    assertFalse(idx.includes(p));

    p = new Person(new Person.Key("q"), 42);
    assertTrue(idx.includes(p));

    idx.encode(b, p);
    assertEqualToBuilderResult(new byte[] {'q'}, b);
  }

  @Test
  public void testOnlyBob() throws Exception {
    IndexFunction<Person> idx = index("isbob", "WHERE name.name = 'bob'");
    assertEquals("isbob", idx.getName());

    IndexKeyBuilder b;
    Person p;

    b = new IndexKeyBuilder();
    p = new Person(new Person.Key("q"), 42);
    assertFalse(idx.includes(p));

    p = new Person(new Person.Key("bob"), 42);
    assertTrue(idx.includes(p));

    idx.encode(b, p);
    assertEqualToBuilderResult(new byte[] {}, b);
  }

  @SuppressWarnings("rawtypes")
  private IndexFunction<Person> index(String name, String query) throws OrmException {
    final QueryModel qm = new QueryModel(people, name, query);
    return new IndexFunctionGen(
            new GeneratedClassLoader(Person.class.getClassLoader()), qm, Person.class)
        .create();
  }

  private static void assertEqualToBuilderResult(byte[] exp, IndexKeyBuilder ic) {
    assertEquals(toString(exp), toString(ic.toByteArray()));
  }

  private static String toString(byte[] bin) {
    StringBuilder dst = new StringBuilder(bin.length * 2);
    for (byte b : bin) {
      dst.append(hexchar[(b >>> 4) & 0x0f]);
      dst.append(hexchar[b & 0x0f]);
    }
    return dst.toString();
  }

  private static final char[] hexchar = {
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', //
    'a', 'b', 'c', 'd', 'e', 'f'
  };
}
