﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Alphaleonis.Win32.Filesystem;

using HIO.Backup.Interface;

namespace HIO.Backup.Logic.Search
{
    public static class LocalDiskCrawler
    {
        public static List<string> GetAllFiles(List<string> directories, IPathFilter filter)
        {
            List<string> Result = Task.Run(() => GetAllFilesAsync(directories, filter)).Result;
            return Result;
        }

        public static async Task<List<string>> GetAllFilesAsync(List<string> directories, IPathFilter filter)
        {
            List<string> Result = new List<string>();
            Queue<string> ToProcess = new Queue<string>(directories);

            while(ToProcess.Count > 0)
            {
                string currentDirectory = ToProcess.Dequeue();

                // If filter disallows dir, skip
                if (!filter.IsAllowed(currentDirectory)) continue;

                string[] subDirectories = null;
                await Task.Run(() => {
                    try
                    {
                        subDirectories = Directory.GetDirectories(currentDirectory);
                    }
                    catch (Exception e)
                    {
                        Console.Error.WriteLine(e);
                    }
                });

                if (subDirectories == null) continue; // If it fails, skip

                // Queue sub-directories 
                foreach (string directory in subDirectories) ToProcess.Enqueue(directory);


                // Add files
                string[] files = null;
                await Task.Run(() => {
                    try
                    {
                        files = Directory.GetFiles(currentDirectory);
                    }
                    catch (Exception e)
                    {
                        Console.Error.WriteLine(e);
                    }
                });

                foreach (string file in files)
                {
                    FileInfo info = new FileInfo(file);
                    if (info.Length > 0 && !Result.Contains(file)) Result.Add(file);
                }
            }

            return Result;
        }

    }
}
