/*
 * Copyright (c) 2017, University of Oslo
 *
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the name of the HISP project nor the names of its contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.hisp.dhis.android.core.program;

import org.hisp.dhis.android.core.arch.handlers.SyncHandler;
import org.hisp.dhis.android.core.common.IdentifiableObjectStore;
import org.hisp.dhis.android.core.data.database.DatabaseAdapter;
import org.hisp.dhis.android.core.dataelement.DataElement;
import org.hisp.dhis.android.core.dataelement.DataElementHandler;
import org.hisp.dhis.android.core.dataelement.DataElementStore;

import java.util.List;

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

public class ProgramStageDataElementHandler {
    private final ProgramStageDataElementStore programStageDataElementStore;
    private final SyncHandler<DataElement> dataElementHandler;
    private final IdentifiableObjectStore<DataElement> dataElementStore;

    ProgramStageDataElementHandler(ProgramStageDataElementStore programStageDataElementStore,
                                   SyncHandler<DataElement> dataElementHandler,
                                   IdentifiableObjectStore<DataElement> dataElementStore) {
        this.programStageDataElementStore = programStageDataElementStore;
        this.dataElementHandler = dataElementHandler;
        this.dataElementStore = dataElementStore;
    }

    void handleProgramStageDataElements(List<ProgramStageDataElement> programStageDataElements) {
        if (programStageDataElements == null) {
            return;
        }
        deleteOrPersistProgramStageDataElements(programStageDataElements);
    }

    /**
     * This method deletes or persists program stage data elements and applies the changes to database.
     * Method will call update with or without programStageSectionUid depending if it exists.
     *
     *
     * @param programStageDataElements
     */
    private void deleteOrPersistProgramStageDataElements(List<ProgramStageDataElement> programStageDataElements) {
        int size = programStageDataElements.size();
        for (int i = 0; i < size; i++) {
            ProgramStageDataElement programStageDataElement = programStageDataElements.get(i);
            boolean readableDataElement = programStageDataElement.dataElement().access().read();

            if (isDeleted(programStageDataElement) || !readableDataElement) {
                programStageDataElementStore.delete(programStageDataElement.uid());
                if (!readableDataElement) {
                    dataElementStore.deleteIfExists(programStageDataElement.dataElement().uid());
                }
            } else {
                int updatedRow;

                    updatedRow = programStageDataElementStore.update(
                            programStageDataElement.uid(),
                            programStageDataElement.code(), programStageDataElement.name(),
                            programStageDataElement.displayName(), programStageDataElement.created(),
                            programStageDataElement.lastUpdated(), programStageDataElement.displayInReports(),
                            programStageDataElement.compulsory(), programStageDataElement.allowProvidedElsewhere(),
                            programStageDataElement.sortOrder(), programStageDataElement.allowFutureDate(),
                            programStageDataElement.dataElement().uid(), programStageDataElement.programStage().uid(),
                            programStageDataElement.uid());


                if (updatedRow <= 0) {
                    programStageDataElementStore.insert(
                            programStageDataElement.uid(), programStageDataElement.code(),
                            programStageDataElement.name(), programStageDataElement.displayName(),
                            programStageDataElement.created(), programStageDataElement.lastUpdated(),
                            programStageDataElement.displayInReports(), programStageDataElement.compulsory(),
                            programStageDataElement.allowProvidedElsewhere(), programStageDataElement.sortOrder(),
                            programStageDataElement.allowFutureDate(), programStageDataElement.dataElement().uid(),
                            programStageDataElement.programStage().uid()
                    );
                }
                dataElementHandler.handle(programStageDataElement.dataElement());
            }
        }
    }

    public static ProgramStageDataElementHandler create(DatabaseAdapter databaseAdapter) {
        return new ProgramStageDataElementHandler(
                new ProgramStageDataElementStoreImpl(databaseAdapter),
                DataElementHandler.create(databaseAdapter),
                DataElementStore.create(databaseAdapter)
        );
    }
}
@@ -3600,16 +3600,85 @@
 get(i);%0A
+            if (programStageDataElement.dataElement() != null) %7B%0A    
         
@@ -3767,16 +3767,20 @@
 ead();%0A%0A
+    
         
@@ -3857,32 +3857,36 @@
                 
+    
 programStageData
@@ -3949,24 +3949,28 @@
             
+    
 if (!readabl
@@ -3977,32 +3977,36 @@
 eDataElement) %7B%0A
+    
                 
@@ -4095,34 +4095,42 @@
                 
-%7D%0A
+    %7D%0A    
             %7D el
@@ -4134,16 +4134,20 @@
  else %7B%0A
+    
         
@@ -5022,24 +5022,28 @@
             
+    
 if (updatedR
@@ -5049,24 +5049,28 @@
 Row %3C= 0) %7B%0A
+    
             
@@ -5134,32 +5134,36 @@
                 
+ 
+   
 programStageData
@@ -5205,24 +5205,28 @@
 ent.code(),%0A
+    
             
@@ -5332,32 +5332,36 @@
                 
+ 
+   
 programStageData
@@ -5410,32 +5410,36 @@
 .lastUpdated(),%0A
+    
                 
@@ -5552,32 +5552,36 @@
                 
+ 
+   
 programStageData
@@ -5647,24 +5647,28 @@
 ortOrder(),%0A
+    
             
@@ -5791,32 +5791,36 @@
                 
+ 
+   
 programStageData
@@ -5864,24 +5864,28 @@
             
+    
 );%0A         
@@ -5883,34 +5883,42 @@
                 
+  
-%7D%0A
+  %7D%0A    
                 
@@ -5979,24 +5979,42 @@
 Element());%0A
+                %7D%0A
             

check if dataelement exists in programstagedataelement