package ru.job4j.monitor;

import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * Created on 12.09.17
 * Thread safe parallel file search.
 * @author Wamdue
 * @version 1.0
 */
@ThreadSafe
public class ParallelSearch {

    public final static String STOP_WORD = "STOP";
    private final Object lock = new Object();
    @GuardedBy("lock")
    private Queue<String> queue = new LinkedList<>();

    private List<String> result = new ArrayList<>();

    private String root;
    private String text;
    private List<String> exts;

    /**
     * Main contructor.
     * @param root - directory to start search.
     * @param text - text to search in files.
     * @param exts - list of extensions to analise.
     */
    public ParallelSearch(String root, String text, List<String> exts) {
        this.root = root;
        this.text = text;
        this.exts = exts;
    }

    /**
     * Starts to thread to filter files.
     * @return list of corrected files.
     */
    public List<String> result() {
        PickFile files = new PickFile();
        Visitor filter = new Visitor();
        Thread fileFilter = new Thread(files);
        Thread textSearch = new Thread(filter);
        fileFilter.start();
        textSearch.start();
        try {
            while (fileFilter.isAlive() && textSearch.isAlive()) {
                Thread.sleep(100);
            }
        } catch(InterruptedException ex) {
            ex.printStackTrace();
        }
        return result;
    }

    /**
     * Class to filter files by extension.
     */
    private class PickFile implements Runnable {
        private File[] files;

        PickFile() {
            files = new File(root).listFiles();
        }

        @Override
        public void run() {
            searchFiles(files);
            queue.offer(ParallelSearch.STOP_WORD);
        }

        private void searchFiles(File[] listFiles) {
            for (File f : listFiles) {
                if (f.isDirectory()) {
                    searchFiles(f.listFiles());
                } else {
                    String ext = f.getName().contains(".")? f.getName().substring(f.getName().indexOf('.') + 1) : " ";
                    if (exts.contains(ext)) {
                        synchronized (lock) {
                            queue.offer(f.getAbsolutePath());
                        }
                    }
                }
            }
        }
    }

    /**
     * Class to analyze files for source text
     */
    private class Visitor implements Runnable {

        @Override
        public void run() {
            List<String> lines;
            Path p;
            String file;
            while (true) {
                try {
                    synchronized (lock) {
                        if (queue.isEmpty()) {
                            Thread.sleep(5);
                            continue;
                        } else {
                            file = queue.poll();
                        }
                    }

                    if (file.equals(ParallelSearch.STOP_WORD)) {
                        System.out.println(result.size());
                        break;
                    }


                    p = Paths.get(file);
                    lines = Files.readAllLines(p);
                    for (String line : lines) {
                        if (line.contains(text)) {
                            result.add(p.toFile().getAbsolutePath());
                            break;
                        }
                    }
                } catch (InterruptedException | IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

@@ -24,47 +24,8 @@
 r;%0A%0A
-import net.jcip.annotations.GuardedBy;%0A
 impo
@@ -110,16 +110,49 @@
 eption;%0A
+import java.nio.charset.Charset;%0A
 import j
@@ -271,22 +271,16 @@
 va.util.
-Linked
 List;%0Aim
@@ -294,39 +294,41 @@
 va.util.
-List;%0Aimport java.util.
+concurrent.LinkedBlocking
 Queue;%0A%0A
@@ -523,16 +523,17 @@
 %22STOP%22;%0A
+%0A
     priv
@@ -540,77 +540,22 @@
 ate 
-final Object lock = new Object();%0A    @GuardedBy(%22lock%22)%0A    private 
+LinkedBlocking
 Queu
@@ -582,20 +582,29 @@
 w Linked
-List
+BlockingQueue
 %3C%3E();%0A%0A 
@@ -2425,54 +2425,8 @@
 ) %7B%0A
-                        synchronized (lock) %7B%0A
     
@@ -2487,34 +2487,8 @@
 ));%0A
-                        %7D%0A
     
@@ -2861,34 +2861,29 @@
     
-synchronized (lock) %7B%0A    
+file = queue.poll();%0A
     
@@ -2906,31 +2906,24 @@
 if (
-queue.isEmpty()) %7B%0A    
+file == null) %7B%0A
     
@@ -2956,16 +2956,17 @@
 .sleep(5
+0
 );%0A     
@@ -2984,20 +2984,16 @@
         
-    
 continue
@@ -2998,116 +2998,8 @@
 ue;%0A
-                        %7D else %7B%0A                            file = queue.poll();%0A                        %7D%0A
     
@@ -3008,33 +3008,32 @@
               %7D%0A
-%0A
                 
@@ -3284,16 +3284,42 @@
 lLines(p
+, Charset.defaultCharset()
 );%0A     
@@ -3720,11 +3720,377 @@
  %7D%0A    %7D
+%0A%0A    public static void main(String%5B%5D args) %7B%0A        List%3CString%3E exts = new ArrayList%3C%3E();%0A        exts.add(%22java%22);%0A        String root = %22/home/alexey/IdeaProjects/%22;%0A        String text = %22main%22;%0A%0A        ParallelSearch search = new ParallelSearch(root, text, exts);%0A        for (String s : search.result()) %7B%0A            System.out.println(s);%0A        %7D%0A    %7D
 %0A%7D%0A

refactor ParallelSearch class, task #1106