package us.dot.its.jpo.ode.storage;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;

import us.dot.its.jpo.ode.OdeProperties;
import us.dot.its.jpo.ode.eventlog.EventLogger;

@Service
public class FileSystemStorageService implements StorageService {
   private static Logger logger = LoggerFactory.getLogger(FileSystemStorageService.class);

   private OdeProperties properties;
   private final Path rootLocation;

   @Autowired
   public FileSystemStorageService(OdeProperties properties) {
      this.properties = properties;

      this.rootLocation = Paths.get(this.properties.getUploadLocation());
      logger.info("Upload location: {}", this.rootLocation);
   }

   @Override
   public void store(MultipartFile file) {
      Path path = this.rootLocation.resolve(file.getOriginalFilename());
      try {
         Files.deleteIfExists(path);
         EventLogger.logger.info("Deleting existing file in shared directory", this.rootLocation);
      } catch (IOException e) {
    	  EventLogger.logger.info("Failed to delete existing file in shared directory", this.rootLocation);
    	  throw new StorageException("Failed to delete existing file " + path, e);
      }
      try {
         if (file.isEmpty()) {
        	EventLogger.logger.info("Failed to store empty file", this.rootLocation);
        	 throw new StorageException("Failed to store empty file " + path);
         }
         logger.debug("Copying file {} to {}", file.getOriginalFilename(), path);
         Files.copy(file.getInputStream(), path);
         EventLogger.logger.info("Copying file into shared directory", this.rootLocation);
      } catch (IOException e) {
    	  EventLogger.logger.info("Failed to store file in shared directory", this.rootLocation);
    	  throw new StorageException("Failed to store file " + path, e);
      }
   }

   @Override
   public Stream<Path> loadAll() {
      try {
         return Files.walk(this.rootLocation, 1).filter(path -> !path.equals(this.rootLocation))
               .map(path -> this.rootLocation.relativize(path));
      } catch (IOException e) {
    	  EventLogger.logger.info("Failed to read stored files", this.rootLocation);
    	  throw new StorageException("Failed to read stored files", e);
      }

   }

   @Override
   public Path load(String filename) {
      return rootLocation.resolve(filename);
   }

   @Override
   public Resource loadAsResource(String filename) {
      try {
         Path file = load(filename);
         Resource resource = new UrlResource(file.toUri());
         if (resource.exists() || resource.isReadable()) {
            return resource;
         } else {
            throw new StorageFileNotFoundException("Could not read file: " + filename);

         }
      } catch (MalformedURLException e) {
         throw new StorageFileNotFoundException("Could not read file: " + filename, e);
      }
   }

   @Override
   public void deleteAll() {
	   FileSystemUtils.deleteRecursively(rootLocation.toFile());
	   EventLogger.logger.info("Deleting", this.rootLocation);
   }

   @Override
   public void init() {
      try {
         Files.createDirectory(rootLocation);
      } catch (IOException e) {
    	  EventLogger.logger.info("Failed to initialize storage service",this.rootLocation);
    	  throw new StorageException("Could not initialize storage", e);
      }
   }
}

@@ -1310,45 +1310,8 @@
 y %7B%0A
-         Files.deleteIfExists(path);%0A
     
@@ -1366,48 +1366,56 @@
 file
- in shared directory%22, this.rootLocation
+: %7B%7D%22, path);%0A         Files.deleteIfExists(path
 );%0A 
@@ -1511,48 +1511,20 @@
 file
- in shared directory%22, this.rootLocation
+: %7B%7D %22, path
 );%0A 
@@ -1583,24 +1583,25 @@
 xisting file
+:
  %22 + path, e
@@ -1693,53 +1693,31 @@
 o(%22F
-a
 ile
-d to store empty file%22, this.rootLocation
+ is empty: %7B%7D%22, path
 );%0A 
@@ -1724,17 +1724,16 @@
        %09
- 
 throw ne
@@ -1757,33 +1757,21 @@
 n(%22F
-a
 ile
-d to store
+ is
  empty
- file
+:
  %22 +
@@ -1868,153 +1868,181 @@
 (), 
-path);%0A         Files.copy(file.getInputStream(), path);%0A         EventLogger.logger.info(%22Copying file into shared directory%22, this.rootLocation
+this.rootLocation);%0A         EventLogger.logger.info(%22Copying file %7B%7D to %7B%7D%22, file.getOriginalFilename(), this.rootLocation);%0A         Files.copy(file.getInputStream(), path
 );%0A 
@@ -2144,16 +2144,19 @@
 irectory
+ %7B%7D
 %22, this.
@@ -2226,24 +2226,56 @@
 re file 
-%22 + path
+in shared directory%22 + this.rootLocation
 , e);%0A  
@@ -2587,28 +2587,33 @@
 to read 
-stored files
+files storedin %7B%7D
 %22, this.
@@ -2681,21 +2681,45 @@
 ead 
+files 
 stored 
-files%22
+in %22 + this.rootLocation
 , e)
@@ -3504,16 +3504,19 @@
 Deleting
+ %7B%7D
 %22, this.
@@ -3731,16 +3731,19 @@
  service
+ %7B%7D
 %22,this.r
@@ -3791,25 +3791,25 @@
 eption(%22
-Could not
+Failed to
  initial
@@ -3819,17 +3819,46 @@
  storage
-%22
+ service %22 + this.rootLocation
 , e);%0A  

Update FileSystemStorageService.java