// Copyright (C) 2014 The Android Open Source Project
//
// 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.schema.sql;

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

import com.google.gwtorm.data.Person;
import com.google.gwtorm.data.PhoneBookDb;
import com.google.gwtorm.data.PhoneBookDb2;
import com.google.gwtorm.jdbc.Database;
import com.google.gwtorm.jdbc.JdbcExecutor;
import com.google.gwtorm.server.OrmConcurrencyException;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.Test;

public abstract class SqlDialectTest {
  protected JdbcExecutor executor;
  protected Connection db;
  protected SqlDialect dialect;
  protected Database<PhoneBookDb> phoneBook;
  protected Database<PhoneBookDb2> phoneBook2;

  @Test
  public void testRollbackTransaction() throws OrmException {
    PhoneBookDb schema = phoneBook.open();
    schema.updateSchema(executor);
    schema.people().beginTransaction(null);
    ArrayList<Person> all = new ArrayList<>();
    all.add(new Person(new Person.Key("Bob"), 18));
    schema.people().insert(all);
    schema.rollback();
    List<Person> r = schema.people().olderThan(10).toList();
    assertEquals(0, r.size());
  }

  @Test
  public void testRollbackNoTransaction() throws Exception {
    PhoneBookDb schema = phoneBook.open();
    schema.updateSchema(executor);
    ArrayList<Person> all = new ArrayList<>();
    all.add(new Person(new Person.Key("Bob"), 18));
    schema.people().insert(all);
    schema.commit();
    schema.rollback();
    List<Person> r = schema.people().olderThan(10).toList();
    assertEquals(1, r.size());
  }

  @Test
  public void testCommitTransaction() throws Exception {
    PhoneBookDb schema = phoneBook.open();
    schema.updateSchema(executor);
    schema.people().beginTransaction(null);
    ArrayList<Person> all = new ArrayList<>();
    all.add(new Person(new Person.Key("Bob"), 18));
    schema.people().insert(all);
    schema.commit();
    List<Person> r = schema.people().olderThan(10).toList();
    assertEquals(1, r.size());
  }

  @Test
  public void testThrowsOrmDuplicateKeyExceptionWhenTryingToInsertDuplicates() throws Exception {
    PhoneBookDb p = phoneBook.open();
    try {
      p.updateSchema(executor);

      final Person.Key pk = new Person.Key("Bob");
      final Person bob = new Person(pk, 18);
      p.people().insert(Collections.singleton(bob));

      p.people().insert(Collections.singleton(bob));
      fail("Expected " + OrmDuplicateKeyException.class);
    } catch (OrmDuplicateKeyException e) {
      assertTrue(e.getCause() instanceof SQLException);
      assertContainsString(e.getMessage(), p.people().getRelationName());
    } finally {
      p.close();
    }
  }

  @Test
  public void testThrowsOrmExceptionForOtherErrors() throws Exception {
    PhoneBookDb p = phoneBook.open();
    try {
      p.updateSchema(executor);

      String invalidKey = null;
      final Person.Key pk = new Person.Key(invalidKey);
      final Person bob = new Person(pk, 18);

      p.people().insert(Collections.singleton(bob));
      fail("Expected " + OrmException.class);
    } catch (OrmException e) {
      assertTrue(e.getCause() instanceof SQLException);
      assertFalse(e instanceof OrmDuplicateKeyException);
      assertContainsString(e.getMessage(), p.people().getRelationName());
    } finally {
      p.close();
    }
  }

  @Test
  public void testInsertExistingRowThrowsOrmDuplicateKeyException() throws Exception {
    PhoneBookDb p = phoneBook.open();
    try {
      p.updateSchema(executor);

      Person bob = new Person(new Person.Key("Bob"), 18);
      p.people().insert(Collections.singleton(bob));

      try {
        p.people().insert(Collections.singleton(bob));
        fail("expected OrmDuplicateKeyException");
      } catch (OrmDuplicateKeyException e) {
        assertEquals(p.people().getRelationName(), e.getMessage());
      }
    } finally {
      p.close();
    }
  }

  @Test
  public void testInsertExistingRowInTransactionThrowsOrmDuplicateKeyException() throws Exception {
    PhoneBookDb p = phoneBook.open();
    try {
      p.updateSchema(executor);

      Person bob = new Person(new Person.Key("Bob"), 18);
      p.people().insert(Collections.singleton(bob));

      p.people().beginTransaction(bob.key());
      try {
        p.people().insert(Collections.singleton(bob));

        try {
          p.commit();
          fail("expected OrmDuplicateKeyException");
        } catch (OrmDuplicateKeyException e) {
          assertEquals(p.people().getRelationName(), e.getMessage());
        }
      } finally {
        p.rollback();
      }
    } finally {
      p.close();
    }
  }

  @Test
  public void testUpdateNonexistentRowThrowsOrmConcurrencyException() throws Exception {
    PhoneBookDb p = phoneBook.open();
    try {
      p.updateSchema(executor);

      Person bob = new Person(new Person.Key("Bob"), 18);

      try {
        p.people().update(Collections.singleton(bob));
        fail("expected OrmConcurrencyException");
      } catch (OrmConcurrencyException e) {
        // Expected.
      }
    } finally {
      p.close();
    }
  }

  @Test
  public void testUpdateNonexistentRowInTransactionThrowsOrmConcurrencyException()
      throws Exception {
    PhoneBookDb p = phoneBook.open();
    try {
      p.updateSchema(executor);

      Person bob = new Person(new Person.Key("Bob"), 18);

      p.people().beginTransaction(bob.key());
      try {
        p.people().update(Collections.singleton(bob));

        try {
          p.commit();
          fail("expected OrmConcurrencyException");
        } catch (OrmConcurrencyException e) {
          // Expected.
        }
      } finally {
        p.rollback();
      }
    } finally {
      p.close();
    }
  }

  @Test
  public void testDeleteNonexistentRowThrowsOrmConcurrencyException() throws Exception {
    PhoneBookDb p = phoneBook.open();
    try {
      p.updateSchema(executor);

      Person bob = new Person(new Person.Key("Bob"), 18);

      try {
        p.people().delete(Collections.singleton(bob));
        fail("expected OrmConcurrencyException");
      } catch (OrmConcurrencyException e) {
        // Expected.
      }
    } finally {
      p.close();
    }
  }

  @Test
  public void testDeleteNonexistentRowInTransactionThrowsOrmConcurrencyException()
      throws Exception {
    PhoneBookDb p = phoneBook.open();
    try {
      p.updateSchema(executor);

      Person bob = new Person(new Person.Key("Bob"), 18);

      p.people().beginTransaction(bob.key());
      try {
        p.people().delete(Collections.singleton(bob));

        try {
          p.commit();
          fail("expected OrmConcurrencyException");
        } catch (OrmConcurrencyException e) {
          // Expected.
        }
      } finally {
        p.rollback();
      }
    } finally {
      p.close();
    }
  }

  private void assertContainsString(String string, String substring) {
    assertNotNull(string);
    assertTrue(string.contains(substring));
  }
}
