package nu.studer.gradle.credentials.domain;

import nu.studer.java.util.OrderedProperties;
import org.gradle.api.UncheckedIOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Manages the storage and retrieval of encrypted credentials.
 */
public final class CredentialsPersistenceManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(CredentialsPersistenceManager.class);

    private final File credentialsFile;

    public CredentialsPersistenceManager(File credentialsFile) {
        this.credentialsFile = credentialsFile;
    }

    public File getCredentialsFile() {
        return new File(credentialsFile.toURI());
    }

    public OrderedProperties readCredentials() {
        // read the file with the encrypted credentials, if it already exists
        File file = getCredentialsFile();
        if (file.exists()) {
            LOGGER.debug("Read existing credentials file: " + file.getAbsolutePath());
            return loadProperties(file);
        } else {
            LOGGER.debug("Credentials file does not exist yet: " + file.getAbsolutePath());
            return new OrderedProperties();
        }
    }

    public void storeCredentials(OrderedProperties credentials) {
        // write the updated credentials
        File file = getCredentialsFile();
        LOGGER.debug("Write updated credentials file: " + file.getAbsolutePath());
        saveProperties(credentials, file);
    }

    private static OrderedProperties loadProperties(File file) {
        try {
            FileInputStream inputStream = new FileInputStream(file);
            try {
                return loadProperties(inputStream);
            } finally {
                inputStream.close();
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    private static OrderedProperties loadProperties(InputStream inputStream) {
        OrderedProperties properties = new OrderedProperties();
        try {
            properties.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
        return properties;
    }

    private static void saveProperties(OrderedProperties properties, File file) {
        try {
            FileOutputStream propertiesFileOutputStream = new FileOutputStream(file);
            try {
                properties.store(propertiesFileOutputStream, null);
            } finally {
                propertiesFileOutputStream.close();
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

}

@@ -859,24 +859,92 @@
 entials() %7B%0A
+        OrderedProperties credentials = createOrderedProperties();%0A%0A
         // r
@@ -1171,39 +1171,32 @@
 ));%0A            
-return 
 loadProperties(f
@@ -1194,16 +1194,29 @@
 perties(
+credentials, 
 file);%0A 
@@ -1319,32 +1319,39 @@
 utePath());%0A    
+    %7D%0A%0A
         return n
@@ -1353,42 +1353,20 @@
 urn 
-new OrderedProperties();%0A        %7D
+credentials;
 %0A   
@@ -1662,32 +1662,52 @@
  private static 
+void loadProperties(
 OrderedPropertie
@@ -1700,37 +1700,33 @@
 deredProperties 
-loadP
+p
 roperties(File f
@@ -1718,17 +1718,18 @@
 operties
-(
+, 
 File fil
@@ -1850,23 +1850,16 @@
         
-return 
 loadProp
@@ -1865,16 +1865,28 @@
 perties(
+properties, 
 inputStr
@@ -2087,76 +2087,28 @@
 tic 
-OrderedProperties loadProperties(InputStream inputStream) %7B%0A        
+void loadProperties(
 Orde
@@ -2135,35 +2135,31 @@
 ties
- = new OrderedProperties();
+, InputStream stream) %7B
 %0A   
@@ -2197,22 +2197,17 @@
 es.load(
-inputS
+s
 tream);%0A
@@ -2210,38 +2210,33 @@
 m);%0A            
-inputS
+s
 tream.close();%0A 
@@ -2329,35 +2329,8 @@
   %7D%0A
-        return properties;%0A
     
@@ -2788,10 +2788,282 @@
 %0A    %7D%0A%0A
+    private static OrderedProperties createOrderedProperties() %7B%0A        return new OrderedProperties.OrderedPropertiesBuilder().%0A                withSuppressDateInComment(true).%0A                withOrdering(String.CASE_INSENSITIVE_ORDER).%0A                build();%0A    %7D%0A%0A
 %7D%0A

Store credentials in well-defined order.