// @topic T11921 Recursive dir traversal with Files.walkFileTree and DirectoryStream
// @brief Using DirectoryStream, BasicFileAttributes, SimpleFileVisitor, FileVisitResult

package week13;

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Scanner;

public class AppMain {
    public static void visitDirectoryItems(Path directoryPath) {
        try {
            Files.walkFileTree(
                    directoryPath,
                    new DirectoryVisitor()
            );
        } catch (IOException ex) {
            System.out.println(
                    "*** ERROR, ["
                    + directoryPath.getFileName()
                    + "] is not a directory.");

        }
    }//visitDirectoryItems

    public static void walkDirectory(Path directoryPath) {
        try {
            Files.walkFileTree(
                    directoryPath,
                    new SimpleFileVisitor< Path>() {// anonymous class
                @Override//////////////////////////////////////////////
                public FileVisitResult visitFile(
                        Path file,
                        BasicFileAttributes attrs
                ) throws IOException {
                    //Invoked for a file in a directory.
                    AppMain.printFileInfo(file);
                    System.out.println();
                    return FileVisitResult.CONTINUE;
                }//visitFile

                @Override//////////////////////////////////////////////
                public FileVisitResult visitFileFailed(
                        Path file,
                        IOException exc
                ) throws IOException {
                    System.out.println(
                            "*** Error file ["
                            + file.toString()
                            + "] could not be visited");
                    //Invoked for a file that could not be visited.            }
                    return FileVisitResult.CONTINUE;
                }//visitFileFailed
                
            }// anonymous class
            );
        } catch (IOException ex) {
            System.out.println(
                    "*** ERROR, ["
                    + directoryPath.getFileName()
                    + "] is not a directory.");

        }
    }//walkDirectory

    public static void traverseDirectory(Path directoryPath) {
        try {
            DirectoryStream<Path> dirStream
                    = Files.newDirectoryStream(directoryPath);

            for (Path path : dirStream) {
                if (Files.isRegularFile(path)) {
                    printFileInfo(path);
                    System.out.println();
                } else {
                    System.out.println("DIR " + path.getFileName());
                    traverseDirectory(path);
                }
            }
        } catch (IOException ex) {
            System.out.println(
                    "*** ERROR, ["
                    + directoryPath.getFileName()
                    + "] is not a directory.");

        }
    }//traverseDirectory

    public static void printFileInfo(Path filePath) {
        System.out.print(filePath.toString());
        try {
            BasicFileAttributes attr
                    = Files.readAttributes(filePath, BasicFileAttributes.class);
            System.out.print(" size " + attr.size());
        } catch (IOException e) {
            System.out.println("IO Exception");
        }
    }//printFileInfo

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        for (;;) {
            String name;
            Scanner keyboard = new Scanner( System.in );
            System.out.print( "Enter a directory path >> " );
            name = keyboard.nextLine();
            if ( name.equals( "quit" ) ) {
                break;
            }

            // demo 1:
            traverseDirectory( Paths.get( name ) );

            // demo 2:
            DirectoryParser parser = new DirectoryParser( Paths.get( name ) );
            parser.traverseDirectory();
            
            // demo 3:
            // using anonymous class
            walkDirectory( Paths.get( name ) );
            
            // demo 4:
            // using normal class
            visitDirectoryItems( Paths.get( name ) );
        }
    }//main

}//class AppMain