using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using CommonLang.Concurrent;

namespace CommonLang.File
{
    public static class CFiles
    {
        public static List<FileInfo> listAllFiles(DirectoryInfo dir)
        {
            List<FileInfo> list = new List<FileInfo>();
            listAllFiles(list, dir);
            return list;
        }

        public static void listAllFiles(List<FileInfo> list, DirectoryInfo dir)
        {
            foreach (FileInfo sub in dir.GetFiles())
            {
                list.Add(sub);
            }
            foreach (DirectoryInfo sub in dir.GetDirectories())
            {
                listAllFiles(list, sub);
            }
        }

        public static void createFile(FileInfo file)
        {
            createDir(file.Directory);
        }

        public static void createDir(DirectoryInfo dir)
        {
            Stack<DirectoryInfo> stack = new Stack<DirectoryInfo>(1);
            while (!dir.Exists)
            {
                stack.Push(dir);
                dir = dir.Parent;
            }
            while (stack.Count > 0)
            {
                DirectoryInfo d = stack.Pop();
                d.Create();
            }
        }

        public static bool fileEquals(FileInfo a, FileInfo b)
        {
            return a.FullName.Equals(b.FullName);
        }


        public static void FileCopy(string srcFile, string dstFile, bool overwrite)
        {
            FileInfo df = new FileInfo(dstFile);
            createDir(df.Directory);
            System.IO.File.Copy(srcFile, dstFile, overwrite);
        }

        public static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs = true, Filter filter = null, AtomicInteger progress = null)
        {
            // Get the subdirectories for the specified directory.
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            DirectoryInfo[] dirs = dir.GetDirectories();

            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

            // If the destination directory doesn't exist, create it. 
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }

            // Get the files in the directory and copy them to the new location.
            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo file in files)
            {
                if (filter != null)
                {
                    bool ignore = false;
                    filter(file, out ignore);
                    if (ignore)
                    {
                        progress.IncrementAndGet();
                        continue;
                    }
                }
                string temppath = Path.Combine(destDirName, file.Name);
                file.CopyTo(temppath, false);
                progress.IncrementAndGet();
            }

            // If copying subdirectories, copy them and their contents to new location. 
            if (copySubDirs)
            {
                foreach (DirectoryInfo subdir in dirs)
                {
                    string temppath = Path.Combine(destDirName, subdir.Name);
                    DirectoryCopy(subdir.FullName, temppath, copySubDirs, filter, progress);
                }
            }
        }

        public delegate void Filter(FileInfo src, out bool ignore);
    }
}