package com.backendless.transaction;

import com.backendless.exceptions.ExceptionMessage;
import com.backendless.persistence.BackendlessSerializer;
import com.backendless.transaction.operations.Operation;
import com.backendless.transaction.operations.OperationAddRelation;
import com.backendless.transaction.payload.Relation;

import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public class UnitOfWorkAddRelationImpl implements UnitOfWorkAddRelation
{
  AtomicInteger countAddRelation = new AtomicInteger( 1 );

  private final List<Operation> operations;

  public UnitOfWorkAddRelationImpl( List<Operation> operations )
  {
    this.operations = operations;
  }

  @Override
  public <E, U> OpResult addToRelation( E parentObject, String columnName, List<U> children )
  {
    Map<String, Object> parentObjectMap = SerializationHelper.serializeEntityToMap( parentObject );
    String parentTable = BackendlessSerializer.getSimpleName( parentObject.getClass() );

    List<Map<String, Object>> childrenMaps = TransactionHelper.convertInstancesToMaps( children );

    return addToRelation( parentTable, parentObjectMap, columnName, childrenMaps );
  }

  @Override
  public OpResult addToRelation( String parentTable, Map<String, Object> parentObject, String columnName,
                                 List<Map<String, Object>> children )
  {
    if( children == null || children.isEmpty() )
      throw new IllegalArgumentException( ExceptionMessage.NULL_EMPTY_BULK );

    return addToRelation( parentTable, parentObject, columnName, null, children );
  }

  @Override
  public <E> OpResult addToRelation( String parentTable, OpResult parentObject, String columnName, List<E> children )
  {
    if( children == null || children.isEmpty() )
      throw new IllegalArgumentException( ExceptionMessage.NULL_EMPTY_BULK );

    List<Map<String, Object>> childrenMaps;
    if( !children.get( 0 ).getClass().isAssignableFrom( Map.class ) )
      childrenMaps = TransactionHelper.convertInstancesToMaps( children );
    else
      childrenMaps = (List<Map<String, Object>>) children;

    if( OperationType.supportEntityDescriptionResultType.contains( parentObject.getOperationType() ) )
      throw new IllegalArgumentException( ExceptionMessage.REF_TYPE_NOT_SUPPORT );

    return addToRelation( parentTable, parentObject.getReference(), columnName, null, childrenMaps );
  }

  @Override
  public <E> OpResult addToRelation( E parentObject, String columnName, String whereClauseForChildren )
  {
    Map<String, Object> parentObjectMap = SerializationHelper.serializeEntityToMap( parentObject );
    String parentTable = BackendlessSerializer.getSimpleName( parentObject.getClass() );

    return addToRelation( parentTable, parentObjectMap, columnName, whereClauseForChildren, null );
  }

  @Override
  public OpResult addToRelation( String parentTable, Map<String, Object> parentObject, String columnName,
                                 String whereClauseForChildren )
  {
    return addToRelation( parentTable, parentObject, columnName, whereClauseForChildren, null );
  }

  @Override
  public OpResult addToRelation( String parentTable, OpResult parentObject, String columnName,
                                 String whereClauseForChildren )
  {
    if( OperationType.supportEntityDescriptionResultType.contains( parentObject.getOperationType() ) )
      throw new IllegalArgumentException( ExceptionMessage.REF_TYPE_NOT_SUPPORT );

    return addToRelation( parentTable, parentObject.getReference(), columnName, whereClauseForChildren, null );
  }

  private OpResult addToRelation( String parentTable, Map<String, Object> parentObject, String columnName,      //TODO parentObject change to String objectId or change server
                                  String whereClauseForChildren, List<Map<String, Object>> children )
  {
    if( parentObject.isEmpty() )
      throw new IllegalArgumentException( ExceptionMessage.NULL_EMPTY_MAP );

    String operationResultId = OperationType.ADD_RELATION + "_" + countAddRelation.getAndIncrement();

    Relation relation = new Relation();
    relation.setParentObject( parentObject );
    relation.setRelationColumn( columnName );
    relation.setConditional( whereClauseForChildren );
    relation.setUnconditional( children );
    OperationAddRelation operationAddRelation = new OperationAddRelation( OperationType.ADD_RELATION, parentTable,
                                                                          operationResultId, relation );

    operations.add( operationAddRelation );

    return TransactionHelper.makeOpResult( operationResultId, OperationType.ADD_RELATION );
  }
}

@@ -27,24 +27,60 @@
 ansaction;%0A%0A
+import com.backendless.Persistence;%0A
 import com.b
@@ -853,35 +853,22 @@
   %7B%0A    
-Map%3C
 String
-, Object%3E
  parentO
@@ -876,54 +876,36 @@
 ject
-Map = SerializationHelper.serialize
+Id = Persistence.get
 Entity
-ToMap
+Id
 ( pa
@@ -1151,35 +1151,34 @@
 le, parentObject
-Map
+Id
 , columnName, ch
@@ -1174,16 +1174,22 @@
 umnName,
+ null,
  childre
@@ -1518,24 +1518,118 @@
 TY_BULK );%0A%0A
+    String parentObjectId = (String) parentObject.get( Persistence.DEFAULT_OBJECT_ID_FIELD );%0A
     return a
@@ -1659,32 +1659,34 @@
 le, parentObject
+Id
 , columnName, nu
@@ -2461,37 +2461,71 @@
 arentObject.
-getReference(
+resolveTo( Persistence.DEFAULT_OBJECT_ID_FIELD 
 ), columnNam
@@ -2678,35 +2678,22 @@
   %7B%0A    
-Map%3C
 String
-, Object%3E
  parentO
@@ -2701,54 +2701,36 @@
 ject
-Map = SerializationHelper.serialize
+Id = Persistence.get
 Entity
-ToMap
+Id
 ( pa
@@ -2828,25 +2828,24 @@
 tClass() );%0A
-%0A
     return a
@@ -2883,19 +2883,18 @@
 ntObject
-Map
+Id
 , column
@@ -3119,24 +3119,118 @@
 ldren )%0A  %7B%0A
+    String parentObjectId = (String) parentObject.get( Persistence.DEFAULT_OBJECT_ID_FIELD );%0A
     return a
@@ -3268,16 +3268,18 @@
 ntObject
+Id
 , column
@@ -3740,21 +3740,55 @@
 ect.
-getReference(
+resolveTo( Persistence.DEFAULT_OBJECT_ID_FIELD 
 ), c
@@ -3888,36 +3888,23 @@
 ntTable,
- Map%3CString,
  Object
-%3E
  parentO
@@ -3932,76 +3932,8 @@
 ame,
-      //TODO parentObject change to String objectId or change server
 %0A   
@@ -4039,119 +4039,8 @@
   %7B%0A
-    if( parentObject.isEmpty() )%0A      throw new IllegalArgumentException( ExceptionMessage.NULL_EMPTY_MAP );%0A%0A
     

remove TODO