package ee.shy.core;

import ee.shy.storage.Hash;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.TeeOutputStream;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;


/**
 * Class for creating and interacting with a repository.
 */
public class Repository {
    /**
     * Repository's root directory.
     */
    private final File repositoryDirectory;

    /**
     * {@link #repositoryDirectory}'s parent directory.
     */
    private final File rootDirectory;

    /**
     * Constructs a new repository class.
     */
    private Repository(File rootDirectory) {
        this.rootDirectory = rootDirectory;
        this.repositoryDirectory = new File(rootDirectory, ".shy");
    }

    /**
     * Tries to find an existing repository in the directory shy was executed or its parent directories.
     * @return repository object if existing repository was found, null otherwise.
     */
    public static Repository newExisting() throws RepositoryNotFoundException {
        File currentDirectory = new File(System.getProperty("user.dir"));
        while (currentDirectory != null) {
            File repositoryDirectory = new File(currentDirectory, ".shy");
            if (repositoryDirectory.exists() && repositoryDirectory.isDirectory()) {
                return new Repository(currentDirectory);
            }
            currentDirectory = currentDirectory.getParentFile();
        }
        throw new RepositoryNotFoundException();
    }

    /**
     * Creates a new repository in the directory where shy was executed.
     * @return a Repository object if repository creation was successful. IOException will be thrown otherwise.
     * @throws IOException
     */
    public static Repository newEmpty() throws IOException {
        File currentDirectory = new File(System.getProperty("user.dir"));
        File repositoryDirectory = new File(currentDirectory, ".shy");
        if (repositoryDirectory.exists() || repositoryDirectory.mkdir()) {
            String[] subDirectories = {"commit", "branches", "tags", "storage"};
            for (String subDirectory : subDirectories) {
                File f = new File(repositoryDirectory, subDirectory);
                if (!f.exists())
                    f.mkdir();
            }

            String[] repositoryFiles = {"author", "current"};
            for (String repositoryFile : repositoryFiles) {
                File f = new File(repositoryDirectory, repositoryFile);
                if (!f.exists())
                    f.createNewFile();
            }

            // The following will be refactored later in the project development(Phase 2)
            File master = new File(new File(repositoryDirectory, "branches"), "master");
            File current = new File(repositoryDirectory, "current");
            master.createNewFile();

            TeeOutputStream teeOutputStream = new TeeOutputStream(new FileOutputStream(master), new FileOutputStream(current));
            teeOutputStream.write(Hash.ZERO.toString().getBytes());
            teeOutputStream.close();

            System.out.println("Initialized a shy repository in " + currentDirectory.getAbsolutePath());

            return new Repository(currentDirectory);

            // TODO: 23.03.16 Figure out how to write/parse JSON. Add necessary details to author
            //System.out.println(System.getProperty("user.name"));
        } else {
            throw new IOException("Repository initialization failed!");
        }
    }

    public void add(File file) throws IOException {
        File repositoryDirectory = new File(Repository.newExisting().rootDirectory.getPath(), ".shy/commit/");
        File fileDir = new File(System.getProperty("user.dir"), file.getPath()).getParentFile();

        File fileRelativePath;

        Path path = Paths.get(fileDir.getPath());
        path = this.rootDirectory.toPath().relativize(path);
        fileRelativePath = path.toFile();

        File fullDir = new File(repositoryDirectory, fileRelativePath.getPath());
        fullDir.mkdirs();

        System.out.println(repositoryDirectory.toString());
        System.out.println(fileRelativePath.toString());
        System.out.println(fullDir.toString());

        File filePath = new File(fileRelativePath, file.getName());
        System.out.println(filePath);
        InputStream input = new FileInputStream(file);
        OutputStream output = new FileOutputStream(new File(repositoryDirectory.getPath(), filePath.getPath()));

        IOUtils.copy(input, output);

        input.close();
        output.close();
    }
}
@@ -3621,32 +3621,12 @@
 ile(
-Repository.newExisting()
+this
 .roo
@@ -3660,24 +3660,25 @@
 /commit/%22);%0A
+%0A
         File
@@ -3682,93 +3682,51 @@
 ile 
-fileDir = new File(System.getProperty(%22user.dir%22), file.getPath()).getParentF
+relativeFilePath = relativeFilePath(f
 ile
-(
 );%0A
-%0A
     
@@ -3739,84 +3739,113 @@
 le f
-ileRelativePath;%0A%0A        Path path = Paths.get(fileDir.getPath()
+ullDir = fullRelativeFilePath(repositoryDirectory, relativeFilePath);%0A        fullDir.mkdirs(
 );%0A
+%0A
         
 path
@@ -3844,127 +3844,190 @@
     
-path = this.rootDirectory.toPath().relativize(path);%0A        fileRelativePath = path.toFile();%0A%0A        File fullDir = 
+File filePath = new File(relativeFilePath, file.getName());%0A        try (InputStream input = new FileInputStream(file)) %7B%0A            try (OutputStream output = new FileOutputStream(
 new 
@@ -4054,21 +4054,23 @@
 tory
-, fileRelativ
+.getPath(), fil
 ePat
@@ -4085,266 +4085,435 @@
 h())
-;%0A        fullDir.mkdirs();%0A%0A        System.out.println(repositoryDirectory.toString()
+)) %7B%0A                IOUtils.copy(input, output);%0A            %7D%0A        %7D%0A    %7D%0A%0A    public void remove(File file) throws IOException %7B%0A        File repositoryDirectory = new File(this.repositoryDirectory.getPath(), %22/commit/%22
 );%0A
+%0A
     
+%7D%0A%0A
     
-System.out.println(fileR
+private File r
 elative
-Path.toString());%0A        System.out.println(fullDir.toString());%0A%0A        File filePath = new File(fileRelativePath, 
+FilePath(File file) %7B%0A        File fileDir = new File(System.getProperty(%22user.dir%22), file.getPath()).getParentFile();%0A%0A        Path path = Paths.get(
 file
+Dir
 .get
-Name
+Path
 ());
@@ -4525,46 +4525,70 @@
     
-System.out.println(fileP
+path = this.rootDirectory.toPath().relativize(p
 ath);%0A
+%0A
         
 Inpu
@@ -4587,115 +4587,80 @@
     
-InputStream input = new FileInputStream(f
+return path.toF
 ile
+(
 );%0A    
+%7D%0A%0A
     
-OutputStream output = new FileOutputStream(new 
+private File fullRelativeFilePath(
 File
-(
+ 
 repo
@@ -4678,125 +4678,108 @@
 tory
-.getPath()
 , 
-filePath.getPath()));%0A%0A        IOUtils.copy(input, output);%0A%0A        input.close();%0A        output.close(
+File relativePath) %7B%0A        return new File(repositoryDirectory.getPath(), relativePath.getPath()
 );%0A 

Create separate methods for finding relative file directories