// Copyright 2008 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.server;

import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.Transaction;
import com.google.gwtorm.data.PersonAccess;
import com.google.gwtorm.data.PhoneBookDb;
import com.google.gwtorm.data.TestPerson;
import com.google.gwtorm.jdbc.Database;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.jdbc.SimpleDataSource;

import junit.framework.TestCase;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

public class PhoneBookDbTestCase extends TestCase {
  private static int runCount;
  protected Database<PhoneBookDb> db;
  private List<PhoneBookDb> openSchemas;

  @Override
  public void setUp() throws Exception {
    super.setUp();

    final Properties p = new Properties();
    p.setProperty("driver", org.h2.Driver.class.getName());
    p.setProperty("url", "jdbc:h2:mem:PhoneBookDb" + (runCount++));
    db = new Database<PhoneBookDb>(new SimpleDataSource(p), PhoneBookDb.class);
    openSchemas = new ArrayList<PhoneBookDb>();
  }

  @Override
  public void tearDown() throws Exception {
    if (openSchemas != null) {
      for (PhoneBookDb schema : openSchemas) {
        schema.close();
      }
      openSchemas = null;
    }
    super.tearDown();
  }

  protected PhoneBookDb open() throws OrmException {
    final PhoneBookDb r = db.open();
    if (r != null) {
      openSchemas.add(r);
    }
    return r;
  }

  protected PhoneBookDb openAndCreate() throws OrmException {
    final PhoneBookDb schema = open();
    schema.createSchema();
    return schema;
  }

  protected Statement statement(final PhoneBookDb schema) throws SQLException {
    return ((JdbcSchema) schema).getConnection().createStatement();
  }

  public void testCreateDatabaseHandle() throws Exception {
    assertNotNull(db);
  }

  public void testOpenSchema() throws Exception {
    final PhoneBookDb schema1 = open();
    assertNotNull(schema1);

    final PhoneBookDb schema2 = open();
    assertNotNull(schema2);
    assertNotSame(schema1, schema2);
  }

  public void testGetPeopleAccess() throws Exception {
    final PhoneBookDb schema = open();
    assertNotNull(schema.people());
  }

  public void testGetAddressAccess() throws Exception {
    final PhoneBookDb schema = open();
    assertNotNull(schema.addresses());
  }

  public void testCreateSchema() throws Exception {
    final PhoneBookDb schema = open();
    schema.createSchema();
  }

  public void testNextAddressId() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final int a = schema.nextAddressId();
    final int b = schema.nextAddressId();
    assertTrue(a != b);
  }

  public void testPersonPrimaryKey() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final TestPerson.Key key = new TestPerson.Key("Bob");
    final TestPerson bob = new TestPerson(key, 18);
    assertSame(key, schema.people().primaryKey(bob));
  }

  public void testInsertOnePerson() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final TestPerson bob = new TestPerson(new TestPerson.Key("Bob"), 18);
    schema.people().insert(Collections.singleton(bob));

    final Statement st = statement(schema);
    final ResultSet rs = st.executeQuery("SELECT name,age FROM people");
    assertTrue(rs.next());
    assertEquals(bob.name(), rs.getString(1));
    assertEquals(bob.age(), rs.getInt(2));
    assertFalse(rs.next());
    rs.close();
    st.close();
  }

  public void testGetOnePerson() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final PersonAccess sp = schema.people();
    final TestPerson p1 = new TestPerson(new TestPerson.Key("Bob"), 18);
    sp.insert(Collections.singleton(p1));

    final TestPerson p2 = sp.get(sp.primaryKey(p1));
    assertNotNull(p2);
    assertNotSame(p1, p2);
    assertEquals(sp.primaryKey(p1), sp.primaryKey(p2));
  }

  public void testGetByAge() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final PersonAccess sp = schema.people();
    final TestPerson p1 = new TestPerson(new TestPerson.Key("Bob"), 18);
    sp.insert(Collections.singleton(p1));

    final TestPerson p2 = sp.byAge(p1.age());
    assertNotNull(p2);
    assertNotSame(p1, p2);
    assertEquals(sp.primaryKey(p1), sp.primaryKey(p2));
  }

  public void testGetOnePersonIterator() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final PersonAccess sp = schema.people();
    final TestPerson p1 = new TestPerson(new TestPerson.Key("Bob"), 18);
    sp.insert(Collections.singleton(p1));

    final List<TestPerson> list =
        sp.get(Collections.singleton(sp.primaryKey(p1))).toList();
    assertNotNull(list);
    assertEquals(1, list.size());

    final TestPerson p2 = list.get(0);
    assertNotNull(p2);
    assertNotSame(p1, p2);
    assertEquals(sp.primaryKey(p1), sp.primaryKey(p2));
  }

  public void testInsertManyPeople() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final ArrayList<TestPerson> all = new ArrayList<TestPerson>();
    all.add(new TestPerson(new TestPerson.Key("Bob"), 18));
    all.add(new TestPerson(new TestPerson.Key("Mary"), 22));
    all.add(new TestPerson(new TestPerson.Key("Zak"), 33));
    schema.people().insert(all);

    final Statement st = statement(schema);
    final ResultSet rs;
    rs = st.executeQuery("SELECT name,age FROM people ORDER BY name");
    for (int rowIdx = 0; rowIdx < all.size(); rowIdx++) {
      assertTrue(rs.next());
      assertEquals(all.get(rowIdx).name(), rs.getString(1));
      assertEquals(all.get(rowIdx).age(), rs.getInt(2));
    }
    assertFalse(rs.next());
    rs.close();
    st.close();
  }

  public void testInsertManyPeopleByTransaction() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final Transaction txn = schema.beginTransaction();
    final ArrayList<TestPerson> all = new ArrayList<TestPerson>();
    all.add(new TestPerson(new TestPerson.Key("Bob"), 18));
    all.add(new TestPerson(new TestPerson.Key("Mary"), 22));
    all.add(new TestPerson(new TestPerson.Key("Zak"), 33));
    schema.people().insert(all, txn);

    final Statement st = statement(schema);
    ResultSet rs;

    rs = st.executeQuery("SELECT name,age FROM people ORDER BY name");
    assertFalse(rs.next());
    rs.close();

    txn.commit();
    rs = st.executeQuery("SELECT name,age FROM people ORDER BY name");
    for (int rowIdx = 0; rowIdx < all.size(); rowIdx++) {
      assertTrue(rs.next());
      assertEquals(all.get(rowIdx).name(), rs.getString(1));
      assertEquals(all.get(rowIdx).age(), rs.getInt(2));
    }
    assertFalse(rs.next());
    rs.close();
    st.close();
  }

  public void testDeleteOnePerson() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final TestPerson bob = new TestPerson(new TestPerson.Key("Bob"), 18);
    schema.people().insert(Collections.singleton(bob));
    schema.people().delete(Collections.singleton(bob));

    final Statement st = statement(schema);
    final ResultSet rs = st.executeQuery("SELECT name,age FROM people");
    assertFalse(rs.next());
    rs.close();
    st.close();
  }

  public void testUpdateOnePerson() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final TestPerson bob = new TestPerson(new TestPerson.Key("Bob"), 18);
    schema.people().insert(Collections.singleton(bob));
    bob.growOlder();
    schema.people().update(Collections.singleton(bob));

    final Statement st = statement(schema);
    final ResultSet rs = st.executeQuery("SELECT name,age FROM people");
    assertTrue(rs.next());
    assertEquals(bob.name(), rs.getString(1));
    assertEquals(bob.age(), rs.getInt(2));
    assertFalse(rs.next());
    rs.close();
    st.close();
  }

  public void testUpdateNoPerson() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final TestPerson bob = new TestPerson(new TestPerson.Key("Bob"), 18);
    try {
      schema.people().update(Collections.singleton(bob));
      fail("Update of missing person succeeded");
    } catch (OrmException e) {
      assertEquals("Update failure: people", e.getMessage());
      assertTrue(e.getCause() instanceof SQLException);
      assertEquals("Entity 1 not affected by update", e.getCause().getMessage());
    }
  }

  public void testFetchOnePerson() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final TestPerson bob = new TestPerson(new TestPerson.Key("Bob"), 18);
    schema.people().insert(Collections.singleton(bob));

    final List<TestPerson> all = schema.people().all().toList();
    assertNotNull(all);
    assertEquals(1, all.size());
    assertNotSame(bob, all.get(0));
    assertEquals(bob.name(), all.get(0).name());
    assertEquals(bob.age(), all.get(0).age());
    assertEquals(bob.isRegistered(), all.get(0).isRegistered());
  }

  public void testFetchOnePersonByName() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final TestPerson bob1 = new TestPerson(new TestPerson.Key("Bob"), 18);
    schema.people().insert(Collections.singleton(bob1));

    final TestPerson bob2 =
        schema.people().get(new TestPerson.Key(bob1.name()));
    assertNotNull(bob2);
    assertNotSame(bob1, bob2);
    assertEquals(bob1.name(), bob2.name());
    assertEquals(bob1.age(), bob2.age());
    assertEquals(bob1.isRegistered(), bob2.isRegistered());
  }

  public void testFetchByAge() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final ArrayList<TestPerson> all = new ArrayList<TestPerson>();
    all.add(new TestPerson(new TestPerson.Key("Bob"), 18));
    all.add(new TestPerson(new TestPerson.Key("Mary"), 22));
    all.add(new TestPerson(new TestPerson.Key("Zak"), 33));
    schema.people().insert(all);

    final List<TestPerson> r = schema.people().olderThan(20).toList();
    assertEquals(2, r.size());
    assertEquals(all.get(1).name(), r.get(0).name());
    assertEquals(all.get(2).name(), r.get(1).name());
  }

  public void testFetchNotPerson() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final ArrayList<TestPerson> all = new ArrayList<TestPerson>();
    all.add(new TestPerson(new TestPerson.Key("Bob"), 18));
    all.add(new TestPerson(new TestPerson.Key("Mary"), 22));
    all.add(new TestPerson(new TestPerson.Key("Zak"), 33));
    schema.people().insert(all);

    final List<TestPerson> r =
        schema.people().notPerson(new TestPerson.Key("Mary"), 10).toList();
    assertEquals(2, r.size());
    assertEquals(all.get(2).name(), r.get(0).name());
    assertEquals(all.get(0).name(), r.get(1).name());
  }

  public void testBooleanType() throws Exception {
    final PhoneBookDb schema = openAndCreate();
    final TestPerson bob = new TestPerson(new TestPerson.Key("Bob"), 18);
    schema.people().insert(Collections.singleton(bob));

    final Statement st = statement(schema);
    ResultSet rs;

    rs = st.executeQuery("SELECT registered FROM people");
    assertTrue(rs.next());
    assertEquals("N", rs.getString(1));
    assertFalse(rs.next());
    rs.close();
    assertEquals(bob.isRegistered(), schema.people().all().toList().get(0)
        .isRegistered());

    bob.register();
    schema.people().update(Collections.singleton(bob));
    rs = st.executeQuery("SELECT registered FROM people");
    assertTrue(rs.next());
    assertEquals("Y", rs.getString(1));
    assertFalse(rs.next());
    rs.close();
    assertEquals(bob.isRegistered(), schema.people().all().toList().get(0)
        .isRegistered());

    bob.unregister();
    schema.people().update(Collections.singleton(bob));
    rs = st.executeQuery("SELECT registered FROM people");
    assertTrue(rs.next());
    assertEquals("N", rs.getString(1));
    assertFalse(rs.next());
    rs.close();
    assertEquals(bob.isRegistered(), schema.people().all().toList().get(0)
        .isRegistered());

    st.close();
  }
}
