package org.leyfer.thesis.touchlogger_dirty.utils.file;

import android.support.annotation.NonNull;
import android.util.Log;

import org.leyfer.thesis.touchlogger_dirty.activity.MainActivity;
import org.leyfer.thesis.touchlogger_dirty.exception.FileIsNotDirectoryException;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Monitors given directory for new files matching given pattern.
 * Created by k.leyfer on 09.10.2017.
 */

public abstract class DirectoryMonitor {

    private static final int SLEEP_INTERVAL = 1000;

    private final File baseDir;
    private final Pattern pattern;

    private boolean stop;
    private Thread monitorThread;

    private final List<File> fileList;

    public DirectoryMonitor(@NonNull File baseDir, @NonNull Pattern pattern)
            throws FileNotFoundException, FileIsNotDirectoryException {

        if (!baseDir.exists()) {
            throw new FileNotFoundException("Unable to find base directory!");
        }

        if (!baseDir.isDirectory()) {
            throw new FileIsNotDirectoryException("Base dir is not a directory!");
        }

        this.pattern = pattern;
        this.baseDir = baseDir;
        fileList = new ArrayList<>();
    }

    public void start() {
        setStop(false);
        monitorThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!shouldStop()) {
                    loopOnce();
                    try {
                        Thread.sleep(SLEEP_INTERVAL);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        monitorThread.start();
    }

    public void stop() {
        setStop(true);

        if (monitorThread != null && monitorThread.isAlive()) {
            try {
                monitorThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        monitorThread = null;
    }


    private void loopOnce() {
        File[] contents = baseDir.listFiles();
        if (contents.length == 0) {
            return;
        }

        List<File> currentFileList = new ArrayList<>();
        for (File childFile : contents) {
            currentFileList.add(childFile);
            Matcher fileNameMatcher = pattern.matcher(childFile.getName());
            if (!fileNameMatcher.matches()) {
                continue;
            }

            if (this.fileList.contains(childFile)) {
                continue;
            }

            this.fileList.add(childFile);
            onFileAdded(childFile);
            Log.d(MainActivity.TAG, String.format("Add %s (%s) to file list",
                    childFile.getAbsolutePath(), childFile.getName()));
        }

        Iterator<File> filesIterator = this.fileList.iterator();
        while (filesIterator.hasNext()) {
            File file = filesIterator.next();
            if (!currentFileList.contains(file)) {
                Log.d(MainActivity.TAG, String.format("Removing deleted file \"%s\" from file list",
                        file.getAbsolutePath()));
                filesIterator.remove();
            }
        }
    }

    public abstract void onFileAdded(File newFile);

    public synchronized void setStop(boolean shouldStop) {
        this.stop = shouldStop;
    }

    public synchronized boolean shouldStop() {
        return this.stop;
    }
}

@@ -1046,86 +1046,155 @@
     
-throw new FileNotFoundException(%22Unable to find base directory!%22);%0A        %7D%0A%0A
+Log.w(MainActivity.TAG, String.format(%22Basedir %5C%22%25s%5C%22 does not exist. Yet?%22,%0A                    baseDir.getAbsolutePath()));%0A        %7D else %7B%0A    
     
@@ -1223,24 +1223,28 @@
 ectory()) %7B%0A
+    
             
@@ -1314,16 +1314,30 @@
 ory!%22);%0A
+            %7D%0A
         
@@ -2303,24 +2303,206 @@
 oopOnce() %7B%0A
+        if (!baseDir.exists()) %7B%0A            Log.w(MainActivity.TAG, String.format(%22Basedir %5C%22%25s%5C%22 does not exist. Yet?%22,%0A                    baseDir.getAbsolutePath()));%0A        %7D%0A%0A
         File
@@ -2556,16 +2556,36 @@
 contents
+ == null %7C%7C contents
 .length 

Handle non-exitstent logs dir properly.