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

import android.support.annotation.NonNull;

import org.hisp.dhis.android.core.arch.handlers.SyncHandler;
import org.hisp.dhis.android.core.common.DataOrphanCleanerImpl;
import org.hisp.dhis.android.core.common.ObjectWithoutUidStore;
import org.hisp.dhis.android.core.common.OrphanCleaner;
import org.hisp.dhis.android.core.common.State;
import org.hisp.dhis.android.core.data.database.DatabaseAdapter;
import org.hisp.dhis.android.core.enrollment.note.Note;
import org.hisp.dhis.android.core.enrollment.note.NoteHandler;
import org.hisp.dhis.android.core.enrollment.note.NoteStore;
import org.hisp.dhis.android.core.enrollment.note.NoteToStoreTransformer;
import org.hisp.dhis.android.core.enrollment.note.NoteUniquenessManager;
import org.hisp.dhis.android.core.event.Event;
import org.hisp.dhis.android.core.event.EventHandler;
import org.hisp.dhis.android.core.event.EventModel;
import org.hisp.dhis.android.core.systeminfo.DHISVersionManager;

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

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

public class EnrollmentHandler {
    private final DHISVersionManager versionManager;
    private final EnrollmentStore enrollmentStore;
    private final SyncHandler<Event> eventHandler;
    private final SyncHandler<Note> noteHandler;
    private final ObjectWithoutUidStore<Note> noteStore;
    private final OrphanCleaner<Enrollment, Event> eventOrphanCleaner;

    EnrollmentHandler(@NonNull DHISVersionManager versionManager,
                      @NonNull EnrollmentStore enrollmentStore,
                      @NonNull SyncHandler<Event> eventHandler,
                      @NonNull OrphanCleaner<Enrollment, Event> eventOrphanCleaner,
                      @NonNull SyncHandler<Note> noteHandler,
                      @NonNull ObjectWithoutUidStore<Note> noteStore) {
        this.versionManager = versionManager;
        this.enrollmentStore = enrollmentStore;
        this.eventHandler = eventHandler;
        this.noteHandler = noteHandler;
        this.noteStore = noteStore;
        this.eventOrphanCleaner = eventOrphanCleaner;
    }

    public void handle(@NonNull List<Enrollment> enrollments) {

        if (enrollments != null && !enrollments.isEmpty()) {
            int size = enrollments.size();

            for (int i = 0; i < size; i++) {
                Enrollment enrollment = enrollments.get(i);
                handle(enrollment);
            }
        }
    }

    private void handle(@NonNull Enrollment enrollment) {
        if (enrollment == null) {
            return;
        }

        if (isDeleted(enrollment)) {
            enrollmentStore.delete(enrollment.uid());
        } else {
            String latitude = null;
            String longitude = null;
            if (enrollment.coordinate() != null) {
                latitude = enrollment.coordinate().latitude().toString();
                longitude = enrollment.coordinate().longitude().toString();
            }

            int updatedRow = enrollmentStore.update(enrollment.uid(), enrollment.created(),
                    enrollment.lastUpdated(),
                    enrollment.createdAtClient(), enrollment.lastUpdatedAtClient(),
                    enrollment.organisationUnit(),
                    enrollment.program(), enrollment.enrollmentDate(),
                    enrollment.incidentDate(),
                    enrollment.followUp(), enrollment.status(),
                    enrollment.trackedEntityInstance(),
                    latitude, longitude,
                    State.SYNCED, enrollment.uid());

            if (updatedRow <= 0) {
                enrollmentStore.insert(enrollment.uid(), enrollment.created(),
                        enrollment.lastUpdated(),
                        enrollment.createdAtClient(), enrollment.lastUpdatedAtClient(),
                        enrollment.organisationUnit(), enrollment.program(),
                        enrollment.enrollmentDate(),
                        enrollment.incidentDate(), enrollment.followUp(),
                        enrollment.status(),
                        enrollment.trackedEntityInstance(), latitude, longitude,
                        State.SYNCED);
            }

            eventHandler.handleMany(enrollment.events());

            Collection<Note> notes = new ArrayList<>();
            NoteToStoreTransformer transformer = new NoteToStoreTransformer(enrollment, versionManager);
            if (enrollment.notes() != null) {
                for (Note note : enrollment.notes()) {
                    notes.add(transformer.transform(note));
                }
            }

            noteHandler.handleMany(NoteUniquenessManager.buildUniqueCollection(notes, enrollment.uid(), noteStore));
        }
        eventOrphanCleaner.deleteOrphan(enrollment, enrollment.events());
    }

    public static EnrollmentHandler create(DatabaseAdapter databaseAdapter, DHISVersionManager versionManager) {
        return new EnrollmentHandler(
                versionManager,
                new EnrollmentStoreImpl(databaseAdapter),
                EventHandler.create(databaseAdapter),
                new DataOrphanCleanerImpl<Enrollment, Event>(EventModel.TABLE, EventModel.Columns.ENROLLMENT,
                        EventModel.Columns.STATE, databaseAdapter),
                NoteHandler.create(databaseAdapter),
                NoteStore.create(databaseAdapter)
        );
    }
}
@@ -85,16 +85,93 @@
 nNull;%0A%0A
+import org.hisp.dhis.android.core.arch.handlers.IdentifiableSyncHandlerImpl;%0A
 import o
@@ -279,32 +279,87 @@
 hanCleanerImpl;%0A
+import org.hisp.dhis.android.core.common.HandleAction;%0A
 import org.hisp.
@@ -466,56 +466,8 @@
 er;%0A
-import org.hisp.dhis.android.core.common.State;%0A
 impo
@@ -1134,110 +1134,76 @@
 on;%0A
-import java.util.List;%0A%0Aimport static org.hisp.dhis.android.core.utils.Utils.isDeleted;%0A%0Apublic class 
+%0Apublic class EnrollmentHandler extends IdentifiableSyncHandlerImpl%3C
 Enro
@@ -1208,23 +1208,17 @@
 rollment
-Handler
+%3E
  %7B%0A    p
@@ -1269,59 +1269,8 @@
 er;%0A
-    private final EnrollmentStore enrollmentStore;%0A
     
@@ -1902,24 +1902,56 @@
 oteStore) %7B%0A
+        super(enrollmentStore);%0A
         this
@@ -1988,56 +1988,8 @@
 er;%0A
-        this.enrollmentStore = enrollmentStore;%0A
     
@@ -2171,2107 +2171,146 @@
     
-public void handle(@NonNull List%3CEnrollment%3E enrollments) %7B%0A%0A        if (enrollments != null && !enrollments.isEmpty()) %7B%0A            int size = enrollments.size();%0A%0A            for (int i = 0; i %3C size; i++) %7B%0A                Enrollment enrollment = enrollments.get(i);%0A                handle(enrollment);%0A            %7D%0A        %7D%0A    %7D%0A%0A    private void handle(@NonNull Enrollment enrollment) %7B%0A        if (enrollment == null) %7B%0A            return;%0A        %7D%0A%0A        if (isDeleted(enrollment)) %7B%0A            enrollmentStore.delete(enrollment.uid());%0A        %7D else %7B%0A            String latitude = null;%0A            String longitude = null;%0A            if (enrollment.coordinate() != null) %7B%0A                latitude = enrollment.coordinate().latitude().toString();%0A                longitude = enrollment.coordinate().longitude().toString();%0A            %7D%0A%0A            int updatedRow = enrollmentStore.update(enrollment.uid(), enrollment.created(),%0A                    enrollment.lastUpdated(),%0A                    enrollment.createdAtClient(), enrollment.lastUpdatedAtClient(),%0A                    enrollment.organisationUnit(),%0A                    enrollment.program(), enrollment.enrollmentDate(),%0A                    enrollment.incidentDate(),%0A                    enrollment.followUp(), enrollment.status(),%0A                    enrollment.trackedEntityInstance(),%0A                    latitude, longitude,%0A                    State.SYNCED, enrollment.uid());%0A%0A            if (updatedRow %3C= 0) %7B%0A                enrollmentStore.insert(enrollment.uid(), enrollment.created(),%0A                        enrollment.lastUpdated(),%0A                        enrollment.createdAtClient(), enrollment.lastUpdatedAtClient(),%0A                        enrollment.organisationUnit(), enrollment.program(),%0A                        enrollment.enrollmentDate(),%0A                        enrollment.incidentDate(), enrollment.followUp(),%0A                        enrollment.status(),%0A                        enrollment.trackedEntityInstance(), latitude, longitude,%0A                        State.SYNCED);%0A            %7D%0A
+@Override%0A    protected void afterObjectHandled(Enrollment enrollment, HandleAction action) %7B%0A        if (action != HandleAction.Delete) %7B
 %0A   
@@ -2715,25 +2715,24 @@
           %7D%0A
-%0A
             
@@ -2838,32 +2838,33 @@
 re));%0A        %7D%0A
+%0A
         eventOrp
@@ -3127,20 +3127,16 @@
         
-new 
 Enrollme
@@ -3146,16 +3146,23 @@
 toreImpl
+.create
 (databas

Unify EnrollmentHandler