package com.novoda.downloadmanager;

import android.content.Context;
import android.support.annotation.Nullable;

import com.novoda.downloadmanager.FilePersistenceResult.Status;
import com.novoda.notils.logger.simple.Log;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

class InternalFilePersistence implements FilePersistence {

    private Context context;

    @Nullable
    private FileOutputStream file;
    @Nullable
    private FileName fileName;

    @Override
    public void initialiseWith(Context context) {
        this.context = context.getApplicationContext();
    }

    @Override
    public FilePersistenceResult create(FileName fileName, FileSize fileSize) {
        if (fileSize.isTotalSizeUnknown()) {
            return FilePersistenceResult.newInstance(Status.ERROR_UNKNOWN_TOTAL_FILE_SIZE);
        }

        long usableSpace = context.getFilesDir().getUsableSpace();
        if (usableSpace < fileSize.totalSize()) {
            return FilePersistenceResult.newInstance(Status.ERROR_INSUFFICIENT_SPACE);
        }

        FilePath filePath = FilePathCreator.create(fileName.name());
        return create(filePath);
    }

    @Override
    public FilePersistenceResult create(FilePath filePath) {
        try {
            file = context.openFileOutput(filePath.path(), Context.MODE_APPEND);
        } catch (FileNotFoundException e) {
            Log.e(e, "File could not be opened");
            return FilePersistenceResult.newInstance(Status.ERROR_OPENING_FILE);
        }

        fileName = LiteFileName.from(filePath.path());
        return FilePersistenceResult.newInstance(Status.SUCCESS, filePath);
    }

    @Override
    public boolean write(byte[] buffer, int offset, int numberOfBytesToWrite) {
        if (file == null) {
            Log.e("Cannot write, you must create the file first");
            return false;
        }

        try {
            file.write(buffer, offset, numberOfBytesToWrite);
            return true;
        } catch (IOException e) {
            Log.e(e, "Exception while writing to internal physical storage");
            return false;
        }
    }

    @Override
    public void delete() {
        if (fileName == null) {
            Log.w("Cannot delete, you must create the file first");
            return;
        }

        context.deleteFile(fileName.name());
    }

    @Override
    public long getCurrentSize() {
        if (file == null) {
            Log.e("Cannot get the current file size, you must create the file first");
            return 0;
        }

        try {
            return file.getChannel().size();
        } catch (IOException e) {
            Log.e(e, "Error requesting file size, make sure you create one first");
            return 0;
        }
    }

    @Override
    public long getCurrentSize(FilePath filePath) {
        FileOutputStream file = null;
        try {
            file = context.openFileOutput(filePath.path(), Context.MODE_APPEND);
            return file.getChannel().size();
        } catch (IOException e) {
            Log.e(e, "Error requesting file size for " + fileName);
            return 0;
        } finally {
            if (file != null) {
                try {
                    file.close();
                } catch (IOException e) {
                    Log.e(e, "Error requesting file size for " + filePath);
                }
            }
        }
    }

    @Override
    public void close() {
        if (file == null) {
            return;
        }

        try {
            file.close();
        } catch (IOException e) {
            Log.e(e, "Failed to close: " + fileName);
        }
    }

    @Override
    public FilePersistenceType getType() {
        return FilePersistenceType.INTERNAL;
    }
}

@@ -216,16 +216,37 @@
 e.Log;%0A%0A
+import java.io.File;%0A
 import j
@@ -275,16 +275,16 @@
 eption;%0A
-
 import j
@@ -1122,62 +1122,218 @@
 File
-Path filePath = FilePathCreator.create(fileName.name()
+ internalFileDir = context.getFilesDir();%0A%0A        String absolutePath = internalFileDir.getAbsolutePath() + File.separatorChar + fileName.name();%0A        FilePath filePath = FilePathCreator.create(absolutePath
 );%0A 
@@ -1498,32 +1498,49 @@
 nFileOutput(
+getLocalNameFrom(
 filePath
 .path(), Con
@@ -1519,38 +1519,32 @@
 ameFrom(filePath
-.path(
 ), Context.MODE_
@@ -1775,24 +1775,41 @@
 me.from(
+getLocalNameFrom(
 filePath
 .path())
@@ -1800,22 +1800,16 @@
 filePath
-.path(
 ));%0A    
@@ -1879,32 +1879,148 @@
 lePath);%0A    %7D%0A%0A
+    private String getLocalNameFrom(FilePath filePath) %7B%0A        return new File(filePath.path()).getName();%0A    %7D%0A%0A
     @Override%0A  
@@ -3282,24 +3282,41 @@
 eOutput(
+getLocalNameFrom(
 filePath
 .path(),
@@ -3307,22 +3307,16 @@
 filePath
-.path(
 ), Conte

Store entire absolute path in FilePath for Internal file persistence