package com.orientechnologies.orient.server.tx;

import com.orientechnologies.orient.core.Orient;
import com.orientechnologies.orient.core.db.OrientDB;
import com.orientechnologies.orient.core.db.OrientDBConfig;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.executor.OResultSet;
import com.orientechnologies.orient.server.OServer;
import com.orientechnologies.orient.server.network.ORemoteImportTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Created by tglman on 03/01/17.
 */
public class RemoteTransactionSupportTest {

  private static final String SERVER_DIRECTORY = "./target/transaction";
  private OServer           server;
  private OrientDB          factory;
  private ODatabaseDocument database;

  @Before
  public void before() throws Exception {
    server = new OServer();
    server.setServerRootDirectory(SERVER_DIRECTORY);
    server.startup(getClass().getResourceAsStream("orientdb-server-config.xml"));
    server.activate();

    factory = OrientDB.remote(new String[] { "localhost" }, OrientDBConfig.defaultConfig());
    factory.create(ORemoteImportTest.class.getSimpleName(), "root", "root", OrientDB.DatabaseType.MEMORY);
    database = factory.open(ORemoteImportTest.class.getSimpleName(), "admin", "admin");
    database.createClass("SomeTx");
    database.createClass("SomeTx2");
  }

  @Test
  public void testQueryUpdateUpdatedInTxTransaction() {
    ODocument doc = new ODocument("SomeTx");
    doc.setProperty("name", "Joe");
    OIdentifiable id = database.save(doc);
    database.begin();
    ODocument doc2 = database.load(id.getIdentity());
    doc2.setProperty("name", "Jane");
    database.save(doc2);
    OResultSet result = database.command("update SomeTx set name='July' where name = 'Jane' ");
    assertEquals((long) result.next().getProperty("count"), 1L);
    ODocument doc3 = database.load(id.getIdentity());
    assertEquals(doc3.getProperty("name"), "July");
  }

  @Test
  public void testQueryUpdateCreatedInTxTransaction() {
    database.begin();
    ODocument doc1 = new ODocument("SomeTx");
    doc1.setProperty("name", "Jane");
    OIdentifiable id = database.save(doc1);

    ODocument docx = new ODocument("SomeTx2");
    docx.setProperty("name", "Jane");
    database.save(docx);

    OResultSet result = database.command("update SomeTx set name='July' where name = 'Jane' ");
    assertTrue(result.hasNext());
    assertEquals((long) result.next().getProperty("count"), 1L);
    ODocument doc2 = database.load(id.getIdentity());
    assertEquals(doc2.getProperty("name"), "July");
    assertFalse(result.hasNext());
  }

  @Test
  public void testRollbackTxTransaction() {
    ODocument doc = new ODocument("SomeTx");
    doc.setProperty("name", "Jane");
    database.save(doc);

    database.begin();
    ODocument doc1 = new ODocument("SomeTx");
    doc1.setProperty("name", "Jane");
    database.save(doc1);

    OResultSet result = database.command("update SomeTx set name='July' where name = 'Jane' ");
    assertTrue(result.hasNext());
    assertEquals((long) result.next().getProperty("count"), 2L);

    database.rollback();

    //This give an index array out of bound error:
    //OResultSet result1 = database.command("select count() from SomeTx where name='Jane'");
    OResultSet result1 = database.command("select count(*) from SomeTx where name='Jane'");
    assertTrue(result1.hasNext());
    // a bit strange name 'count(*)'
    assertEquals((long) result1.next().getProperty("count(*)"), 1L);

  }

  @After
  public void after() {
    database.close();
    factory.close();
    server.shutdown();
    Orient.instance().startup();
  }

}

@@ -3367,61 +3367,512 @@
     
-//This give an index array out of bound error:
+OResultSet result1 = database.command(%22select count(*) from SomeTx where name='Jane'%22);%0A    assertTrue(result1.hasNext());%0A    assertEquals((long) result1.next().getProperty(%22count(*)%22), 1L);%0A%0A  %7D%0A%0A  @Test%0A  public void testRollbackTxChekcStatusTransaction() %7B%0A    ODocument doc = new ODocument(%22SomeTx%22);%0A    doc.setProperty(%22name%22, %22Jane%22);%0A    database.save(doc);%0A%0A    database.begin();%0A    ODocument doc1 = new ODocument(%22SomeTx%22);%0A    doc1.setProperty(%22name%22, %22Jane%22);%0A    database.save(doc1);%0A
 %0A    
-//
 ORes
@@ -3876,33 +3876,32 @@
 ResultSet result
-1
  = database.comm
@@ -3918,16 +3918,17 @@
 t count(
+*
 ) from S
@@ -3946,28 +3946,213 @@
  name='Jane'
+ 
 %22);%0A
+    assertTrue(result.hasNext());%0A    assertEquals((long) result.next().getProperty(%22count(*)%22), 2L);%0A%0A    assertTrue(database.getTransaction().isActive());%0A%0A    database.rollback();%0A%0A
     OResultS
@@ -4270,45 +4270,8 @@
 ));%0A
-    // a bit strange name 'count(*)'%0A
     
@@ -4328,32 +4328,88 @@
 unt(*)%22), 1L);%0A%0A
+    assertFalse(database.getTransaction().isActive());%0A%0A
   %7D%0A%0A  @After%0A  

add test case for check status of transaction in case of remote, issue #7133