package org.hisp.dhis.android.core.trackedentity;

import android.support.annotation.NonNull;

import org.hisp.dhis.android.core.common.ObjectWithoutUidStore;
import org.hisp.dhis.android.core.common.State;
import org.hisp.dhis.android.core.data.database.DatabaseAdapter;
import org.hisp.dhis.android.core.enrollment.Enrollment;
import org.hisp.dhis.android.core.enrollment.EnrollmentHandler;
import org.hisp.dhis.android.core.relationship.Relationship;
import org.hisp.dhis.android.core.relationship.RelationshipModel;
import org.hisp.dhis.android.core.relationship.RelationshipModelBuilder;
import org.hisp.dhis.android.core.relationship.RelationshipStore;

import java.util.Collection;
import java.util.List;

import static org.hisp.dhis.android.core.utils.Utils.isDeleted;

public class TrackedEntityInstanceHandler {
    private final TrackedEntityInstanceStore trackedEntityInstanceStore;
    private final ObjectWithoutUidStore<RelationshipModel> relationshipStore;
    private final TrackedEntityAttributeValueHandler trackedEntityAttributeValueHandler;
    private final EnrollmentHandler enrollmentHandler;

    public TrackedEntityInstanceHandler(
            @NonNull TrackedEntityInstanceStore trackedEntityInstanceStore,
            @NonNull ObjectWithoutUidStore relationshipStore,
            @NonNull TrackedEntityAttributeValueHandler trackedEntityAttributeValueHandler,
            @NonNull EnrollmentHandler enrollmentHandler) {
        this.trackedEntityInstanceStore = trackedEntityInstanceStore;
        this.relationshipStore = relationshipStore;
        this.trackedEntityAttributeValueHandler = trackedEntityAttributeValueHandler;
        this.enrollmentHandler = enrollmentHandler;
    }

    public void handle(@NonNull TrackedEntityInstance trackedEntityInstance) {
        if (trackedEntityInstance == null) {
            return;
        }

        if (isDeleted(trackedEntityInstance)) {
            trackedEntityInstanceStore.delete(trackedEntityInstance.uid());
        } else {
            int updatedRow = trackedEntityInstanceStore.update(
                    trackedEntityInstance.uid(), trackedEntityInstance.created(), trackedEntityInstance.lastUpdated(),
                    trackedEntityInstance.createdAtClient(), trackedEntityInstance.lastUpdatedAtClient(),
                    trackedEntityInstance.organisationUnit(), trackedEntityInstance.trackedEntityType(),
                    trackedEntityInstance.coordinates(), trackedEntityInstance.featureType(),
                    State.SYNCED, trackedEntityInstance.uid());

            if (updatedRow <= 0) {
                trackedEntityInstanceStore.insert(
                        trackedEntityInstance.uid(), trackedEntityInstance.created(),
                        trackedEntityInstance.lastUpdated(), trackedEntityInstance.createdAtClient(),
                        trackedEntityInstance.lastUpdatedAtClient(), trackedEntityInstance.organisationUnit(),
                        trackedEntityInstance.trackedEntityType(), trackedEntityInstance.coordinates(),
                        trackedEntityInstance.featureType(), State.SYNCED);
            }

            trackedEntityAttributeValueHandler.handle(
                    trackedEntityInstance.uid(),
                    trackedEntityInstance.trackedEntityAttributeValues());

            List<Enrollment> enrollments = trackedEntityInstance.enrollments();

            enrollmentHandler.handle(enrollments);

            RelationshipModelBuilder relationshipModelBuilder = new RelationshipModelBuilder();
            for (Relationship relationship : trackedEntityInstance.relationships()) {
                this.handle(relationship.relative());
                this.relationshipStore.updateOrInsertWhere(relationshipModelBuilder.buildModel(relationship));
            }
        }
    }

    public void handleMany(@NonNull Collection<TrackedEntityInstance> trackedEntityInstances) {
        for (TrackedEntityInstance trackedEntityInstance : trackedEntityInstances) {
            handle(trackedEntityInstance);
        }
    }

    public static TrackedEntityInstanceHandler create(DatabaseAdapter databaseAdapter) {
        return new TrackedEntityInstanceHandler(
                new TrackedEntityInstanceStoreImpl(databaseAdapter),
                RelationshipStore.create(databaseAdapter),
                TrackedEntityAttributeValueHandler.create(databaseAdapter),
                EnrollmentHandler.create(databaseAdapter)
        );
    }
}

@@ -1784,20 +1784,44 @@
 Instance
+, boolean asRelationship
 ) %7B%0A
-
         
@@ -2029,16 +2029,17 @@
  else %7B%0A
+%0A
         
@@ -2046,11 +2046,391 @@
     
-int
+State newState = State.SYNCED;%0A            State currentState = null;%0A            if (asRelationship) %7B%0A                currentState = trackedEntityInstanceStore.getState(trackedEntityInstance.uid());%0A                newState = State.RELATIONSHIP;%0A            %7D%0A%0A            int updatedRow = 0;%0A            if (!asRelationship %7C%7C currentState == State.RELATIONSHIP) %7B%0A               
  upd
@@ -2474,16 +2474,20 @@
 update(%0A
+    
         
@@ -2609,32 +2609,36 @@
                 
+ 
+   
 trackedEntityIns
@@ -2699,32 +2699,36 @@
 atedAtClient(),%0A
+    
                 
@@ -2828,32 +2828,36 @@
                 
+    
 trackedEntityIns
@@ -2934,28 +2934,28 @@
         
+  
+  new
 State
-.SYNCED
 , tracke
@@ -2973,24 +2973,38 @@
 ance.uid());
+%0A            %7D
 %0A%0A          
@@ -3543,28 +3543,24 @@
 Type(), 
+new
 State
-.SYNCED
 );%0A     
@@ -4115,16 +4115,22 @@
 lative()
+, true
 );%0A     
@@ -4439,32 +4439,32 @@
 ityInstances) %7B%0A
-
             hand
@@ -4487,16 +4487,23 @@
 Instance
+, false
 );%0A     

save relationships as relationship on tei state