package uk.ac.ebi.spot.goci.curation.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import uk.ac.ebi.spot.goci.curation.exception.FileUploadException;
import uk.ac.ebi.spot.goci.curation.exception.NoStudyDirectoryException;
import uk.ac.ebi.spot.goci.curation.model.StudyFileSummary;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by emma on 15/04/2016.
 *
 * @author emma
 *         <p>
 *         Service to handle upload and download of study files
 */
@Service
public class StudyFileService {

    @Value("${study.directory}")
    private File studyDirRoot;

    private Logger log = LoggerFactory.getLogger(getClass());

    protected Logger getLog() {
        return log;
    }

    public synchronized void createStudyDir(Long studyId) {

        if (getStudyDirRoot() == null) {
            getLog().error("Cannot find root dir for study with ID" + studyId);
            throw new IllegalStateException("Cannot find root directory");
        }

        if (!getStudyDirRoot().exists()) {
            getLog().debug("Making root directory '" + getStudyDirRoot().getAbsolutePath() + "'...");
            boolean success = getStudyDirRoot().mkdirs();
            if (success) {
                getLog().debug("Directory created!");
            }
            else {
                getLog().error("Directory not created for study with ID: " + studyId);
                throw new NoStudyDirectoryException("Directory not created for study");
            }
        }

        boolean success = getStudyDirPath(studyId).mkdir();
        if (!success) {
            getLog().error("Could not create directory for study with ID " + studyId);
            throw new NoStudyDirectoryException("Could not create directory for a study");
        }
    }


    public List<StudyFileSummary> getStudyFiles(Long studyId) {
        List<StudyFileSummary> files = new ArrayList<>();
        File pathToStudyDir = getStudyDirPath(studyId);

        if (pathToStudyDir.exists()) {
            File[] filesInDir = pathToStudyDir.listFiles();

            if (filesInDir != null) {
                for (File file : filesInDir) {
                    // Ignore any hidden files
                    if (!file.isHidden()) {

                        try {
                            StudyFileSummary studyFileSummary =
                                    new StudyFileSummary(file.getName(), file.getCanonicalPath());
                            files.add(studyFileSummary);
                        }
                        catch (IOException e) {
                            getLog().error("Unable to get details of files in directory");
                            throw new FileUploadException("Unable to get details of files in directory");
                        }
                    }
                }
            }
        }
        else {
            getLog().error("No study directory found for study with ID: " + studyId);
        }
        return files;
    }

    public synchronized void upload(MultipartFile fileFromUpload, Long studyId) throws IOException {

        if (!fileFromUpload.isEmpty()) {
            File file = createFileInStudyDir(fileFromUpload.getOriginalFilename(), studyId);

            // Copy contents of multipart request to newly created file
            try {
                fileFromUpload.transferTo(file);
                // Set some permissions
                file.setWritable(true, false);
                file.setReadable(true, false);
            }
            catch (IOException e) {
                getLog().error("Unable to copy file: " + fileFromUpload.getName() + " to study dir");
                throw new FileUploadException("Unable to copy file");
            }
        }
        else {
            getLog().error(fileFromUpload.getName() + " is empty");
            throw new FileUploadException("Upload file is empty");
        }
    }

    /**
     * Create a subdir based on the study id
     *
     * @param id Study ID
     */
    private File getStudyDirPath(Long id) {
        String uploadDirName = getStudyDirRoot() + File.separator + id;
        return new File(uploadDirName);
    }

    /**
     * Create a file object
     *
     * @param name Name of file
     * @param id   Study ID
     */
    private File createFileInStudyDir(String name, Long id) throws IOException {

        // Check study dir exists, if not create it
        File studyDirPath = getStudyDirPath(id);
        if (!studyDirPath.exists()) {
            createStudyDir(id);
        }

        String fileName = getStudyDirRoot() + File.separator + id + File.separator + name;
        File file = new File(fileName);
        boolean success = file.createNewFile();

        if (!success) {
            getLog().error("Could not create a file: " + fileName);
            throw new FileUploadException("Could not create a file");
        }
        return file;
    }

    public File getStudyDirRoot() {
        return studyDirRoot;
    }
}
@@ -2446,25 +2446,24 @@
 Hidden()) %7B%0A
-%0A
             
@@ -2466,35 +2466,50 @@
                 
-try
+if (file.exists())
  %7B%0A             
@@ -2634,33 +2634,8 @@
 me()
-, file.getCanonicalPath()
 );%0A 
@@ -2740,298 +2740,150 @@
     
+%7D%0A
     
-catch (IOException e) %7B%0A                            getLog().error(%22Unable to get details of files in directory%22);%0A                            throw new FileUploadException(%22Unable to get details of files in directory%22);%0A                        %7D%0A                    %7D%0A                %7D
+            %7D%0A            %7D%0A            else %7B%0A                getLog().error(%22No study directory found for study with ID: %22 + studyId);
 %0A   
@@ -2974,39 +2974,86 @@
 ound
- for study with ID: %22 + studyId
+%22);%0A            throw new NoStudyDirectoryException(%22No study directory found%22
 );%0A 
@@ -5017,32 +5017,458 @@
 rn file;%0A    %7D%0A%0A
+    /**%0A     * Get file by study ID and path%0A     *%0A     * @param studyId  Study ID, this will help locate dir%0A     * @param fileName Name of file to return%0A     */%0A    public File getFileFromFileName(Long studyId, String fileName) %7B%0A        String fileNameWithFullPath = getStudyDirRoot() + File.separator + studyId + File.separator + fileName;%0A        File file = new File(fileNameWithFullPath);%0A        return file;%0A    %7D%0A%0A
     public File 

Add method to get a file by supplied name