package org.mbari.vars.ui.commands;

import org.mbari.vars.ui.UIToolBox;
import org.mbari.vars.ui.events.AnnotationsAddedEvent;
import org.mbari.vars.ui.events.AnnotationsRemovedEvent;
import org.mbari.vars.ui.events.AnnotationsSelectedEvent;
import org.mbari.vars.services.model.Annotation;
import org.mbari.vars.services.model.Association;
import org.mbari.vars.services.model.Media;

import java.time.Duration;
import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author Brian Schlining
 * @since 2017-07-20T22:23:00
 */
public class DuplicateAnnotationsCmd implements Command {

    private final Collection<Annotation> duplicateAnnotations;
    private final boolean selectAnnotations;

    public DuplicateAnnotationsCmd(String user, String activity, Collection<Annotation> sourceAnnotations,
                                   boolean selectAnnotations) {
        this.duplicateAnnotations = sourceAnnotations.stream()
                .map(a -> makeDuplicate(a, user, activity))
                .collect(Collectors.toList());
        this.selectAnnotations = selectAnnotations;
    }

    public Annotation makeDuplicate(Annotation annotation, String user, String activity) {
        Annotation duplicate = new Annotation(annotation);
        duplicate.setObservationUuid(null);
        duplicate.setObservationTimestamp(Instant.now());
        duplicate.setObserver(user);
        duplicate.setActivity(activity);

        // M3-41 - video lab doesn't want associations copied
        duplicate.setAssociations(Collections.emptyList());

        // if we don't null the associations uuid, it will fail to insert due to
        // a duplicate primary key clash.
//        duplicate.getAssociations().forEach(Association::resetUuid);
        return duplicate;
    }

    @Override
    public void apply(UIToolBox toolBox) {
        Media media = toolBox.getData().getMedia();
        if (media.getStartTimestamp() != null ) {
            duplicateAnnotations.forEach(annotation -> {
                Duration elapsedTime = annotation.getElapsedTime();
                // Calculate timestamp from media start time and annotation elapsed time
                if (elapsedTime != null) {
                    Instant recordedDate = media.getStartTimestamp().plus(elapsedTime);
                    annotation.setRecordedTimestamp(recordedDate);
                }
            });

        }

        toolBox.getServices()
                .getAnnotationService()
                .createAnnotations(duplicateAnnotations)
                .thenAccept(annos -> {
                    // Replace our existing dups with the ones with the correct observation uuids
                    duplicateAnnotations.clear();
                    duplicateAnnotations.addAll(annos);
                    toolBox.getEventBus()
                            .send(new AnnotationsAddedEvent(annos));
                    if (selectAnnotations) {
                        toolBox.getEventBus()
                                .send(new AnnotationsSelectedEvent(annos));
                    }
                });
    }

    @Override
    public void unapply(UIToolBox toolBox) {
        final Collection<UUID> uuids = duplicateAnnotations.stream()
                .map(Annotation::getObservationUuid)
                .collect(Collectors.toList());

        toolBox.getServices()
                .getAnnotationService()
                .deleteAnnotations(uuids)
                .thenAccept(v ->
                   toolBox.getEventBus()
                        .send(new AnnotationsRemovedEvent(duplicateAnnotations)));
    }

    @Override
    public String getDescription() {
        return "Duplicate Annotations";
    }
}

@@ -454,71 +454,9 @@
 til.
-Collection;%0Aimport java.util.Collections;%0Aimport java.util.UUID
+*
 ;%0Aim
@@ -1273,16 +1273,17 @@
 ation);%0A
+%0A
         
@@ -1451,24 +1451,128 @@
 activity);%0A%0A
+        // M3-52: Don't duplicate imaged-moments%0A        duplicate.setImages(Collections.emptyList());%0A%0A
         // M
@@ -1686,202 +1686,8 @@
 );%0A%0A
-        // if we don't null the associations uuid, it will fail to insert due to%0A        // a duplicate primary key clash.%0A//        duplicate.getAssociations().forEach(Association::resetUuid);%0A
     
@@ -1927,24 +1927,105 @@
 tation -%3E %7B%0A
+                annotation.setVideoReferenceUuid(media.getVideoReferenceUuid());%0A
             
@@ -2575,24 +2575,176 @@
 (annos -%3E %7B%0A
+                    // Filter out any that already exist in the table%0A                    List%3CAnnotation%3E newAnnos = filterPrexisting(toolBox, annos);%0A
             
@@ -2927,17 +2927,20 @@
 .addAll(
-a
+newA
 nnos);%0A 
@@ -3032,33 +3032,36 @@
 tionsAddedEvent(
-a
+newA
 nnos));%0A        
@@ -3210,17 +3210,20 @@
 edEvent(
-a
+newA
 nnos));%0A
@@ -3263,32 +3263,33 @@
      %7D);%0A    %7D%0A%0A
+%0A
     @Override%0A  
@@ -3769,32 +3769,491 @@
 ions)));%0A    %7D%0A%0A
+    private List%3CAnnotation%3E filterPrexisting(UIToolBox toolBox, Collection%3CAnnotation%3E annotations) %7B%0A        List%3CAnnotation%3E existingAnnotations = new ArrayList%3C%3E(toolBox.getData().getAnnotations());%0A        List%3CAnnotation%3E newAnnotations = new ArrayList%3C%3E();%0A        for (Annotation a: annotations) %7B%0A            if (!existingAnnotations.contains(a)) %7B%0A                newAnnotations.add(a);%0A            %7D%0A        %7D%0A        return newAnnotations;%0A    %7D%0A%0A
     @Override%0A  

Fix for copying annotations to new timecode