package com.spectralogic.dsbrowser.gui.services.savedSessionStore;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.spectralogic.dsbrowser.gui.services.sessionStore.Session;
import com.spectralogic.dsbrowser.gui.util.JsonMapping;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;

public class SavedSessionStore {
    private final static Logger LOG = LoggerFactory.getLogger(SavedSessionStore.class);
    private final static Path PATH = Paths.get(System.getProperty("user.home"), ".dsbrowser", "sessions.json");

    private final ObservableList<SavedSession> sessions;

    private boolean dirty = false;

    public static SavedSessionStore loadSavedSessionStore() throws IOException {
        final List<SavedSession> sessions;
        if (Files.exists(PATH)) {
            try (final InputStream inputStream = Files.newInputStream(PATH)) {
                final SerializedSessionStore store = JsonMapping.fromJson(inputStream, SerializedSessionStore.class);
                sessions = store.getSessions();
            }
        } else {
            LOG.info("Creating new empty saved session store");
            sessions = new ArrayList<>();
        }
        return new SavedSessionStore(sessions);
    }

    public static void saveSavedSessionStore(final SavedSessionStore sessionStore) throws IOException {
        if (sessionStore.dirty) {
            LOG.info("Session store was dirty, saving...");
            final SerializedSessionStore store = new SerializedSessionStore(sessionStore.sessions);
            if (!Files.exists(PATH.getParent())) {
                Files.createDirectories(PATH.getParent());
            }
            try (final OutputStream outputStream = Files.newOutputStream(PATH, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE)) {
                JsonMapping.toJson(outputStream, store);
            }
        }
    }

    private SavedSessionStore(final List<SavedSession> sessionList) {
        this.sessions = FXCollections.observableArrayList(sessionList);
        this.sessions.addListener((ListChangeListener<SavedSession>) c -> {
            if (c.next() && (c.wasAdded() || c.wasRemoved())) {
                dirty = true;
            }
        });
    }

    public ObservableList<SavedSession> getSessions() {
        return sessions;
    }

    public void saveSession(final Session session) {
        this.sessions.add(
                new SavedSession(session.getSessionName(),
                        session.getEndpoint(),
                        SavedCredentials.fromCredentials(session.getClient().getConnectionDetails().getCredentials())));
    }

    public void removeSession(final SavedSession sessionName) {
        this.sessions.remove(sessionName);
    }

    private static class SerializedSessionStore {
        @JsonProperty("sessions")
        private final List<SavedSession> sessions;

        @JsonCreator
        private SerializedSessionStore(@JsonProperty("sessions") final List<SavedSession> sessions) {
            this.sessions = sessions;
        }

        public List<SavedSession> getSessions() {
            return sessions;
        }
    }
}

@@ -418,24 +418,59 @@
 rvableList;%0A
+import javafx.scene.control.Alert;%0A
 import org.s
@@ -2852,37 +2852,36 @@
 sion) %7B%0A        
-this.
+if (
 sessions.add(%0A  
@@ -2877,12 +2877,19 @@
 ons.
-add(
+size()==0)%7B
 %0A   
@@ -2897,20 +2897,34 @@
         
-    
+this.sessions.add(
 new Save
@@ -2961,32 +2961,308 @@
 e(),
-%0A                       
+ session.getEndpoint(),%0A                    SavedCredentials.fromCredentials(session.getClient().getConnectionDetails().getCredentials())));%0A        %7D%0A        else if (!containsSessionName(sessions, session.getSessionName())) %7B%0A            this.sessions.add(new SavedSession(session.getSessionName(),
  ses
@@ -3273,36 +3273,32 @@
 .getEndpoint(),%0A
-    
                 
@@ -3394,24 +3394,753 @@
 tials())));%0A
+        %7D%0A        else%0A        %7B%0A            final Alert alert = new Alert(Alert.AlertType.ERROR);%0A            alert.setHeaderText(null);%0A            alert.setTitle(%22New User Session%22);%0A            alert.setContentText(%22Session name already in use. Please use a different name.%22);%0A            alert.showAndWait();%0A        %7D%0A    %7D%0A%0A    public boolean containsSessionName(final ObservableList%3CSavedSession%3E list, final String name) %7B%0A        return list.stream().filter(o -%3E o.getName().equals(name)).findFirst().isPresent();%0A    %7D%0A%0A    public boolean containsNewSessionName(final ObservableList%3CSession%3E list, final String name) %7B%0A        return list.stream().filter(o -%3E o.getSessionName().equals(name)).findFirst().isPresent();%0A
     %7D%0A%0A    p

Create bucket, Delete objects and folder, Physical placement, Internationalization, few user session validations