﻿// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
// 
//   http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.AccessControl;

namespace Org.Apache.REEF.IO.Files
{
    /// <summary>
    /// This is meant only as a proxy class for <see cref="DirectoryInfo"/> and has no 
    /// relation to classes in <see cref="Org.Apache.REEF.IO.FileSystem"/>.
    /// To create a <see cref="DefaultDirectoryInfo"/> object from a <see cref="DirectoryInfo"/> object,
    /// please use the static factory method <see cref="FromDirectoryInfo"/>.
    /// </summary>
    public sealed class DefaultDirectoryInfo : IDirectoryInfo
    {
        private readonly DirectoryInfo _directoryInfo;

        private DefaultDirectoryInfo(DirectoryInfo info)
        {
            _directoryInfo = info;
        }

        /// <summary>
        /// Factory method to create an <see cref="IDirectoryInfo"/> object
        /// from a <see cref="DirectoryInfo"/> object.
        /// </summary>
        public static IDirectoryInfo FromDirectoryInfo(DirectoryInfo info)
        {
            return new DefaultDirectoryInfo(info);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Attributes"/>.
        /// </summary>
        public FileAttributes Attributes
        {
            get { return _directoryInfo.Attributes; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#CreationTime"/>.
        /// </summary>
        public DateTime CreationTime
        {
            get { return _directoryInfo.CreationTime; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#CreationTimeUtc"/>.
        /// </summary>
        public DateTime CreationTimeUtc
        {
            get { return _directoryInfo.CreationTimeUtc; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Exists"/>.
        /// </summary>
        public bool Exists
        {
            get { return _directoryInfo.Exists; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Extension"/>.
        /// </summary>
        public string Extension
        {
            get { return _directoryInfo.Extension; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#FullName"/>.
        /// </summary>
        public string FullName
        {
            get { return _directoryInfo.FullName; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#LastAccessTime"/>.
        /// </summary>
        public DateTime LastAccessTime
        {
            get { return _directoryInfo.LastAccessTime; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#LastAccessTimeUtc"/>.
        /// </summary>
        public DateTime LastAccessTimeUtc
        {
            get { return _directoryInfo.LastAccessTimeUtc; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#LastWriteTime"/>.
        /// </summary>
        public DateTime LastWriteTime
        {
            get { return _directoryInfo.LastWriteTime; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#LastWriteTimeUtc"/>.
        /// </summary>
        public DateTime LastWriteTimeUtc
        {
            get { return _directoryInfo.LastWriteTimeUtc; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Name"/>.
        /// </summary>
        public string Name
        {
            get { return _directoryInfo.Name; }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Parent"/>.
        /// </summary>
        public IDirectoryInfo Parent
        {
            get { return FromDirectoryInfo(_directoryInfo.Parent); }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Root"/>.
        /// </summary>
        public IDirectoryInfo Root
        {
            get { return FromDirectoryInfo(_directoryInfo.Root); }
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Delete"/>.
        /// </summary>
        public void Delete()
        {
            _directoryInfo.Delete();
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Refresh"/>.
        /// </summary>
        public void Refresh()
        {
            _directoryInfo.Refresh();
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Create"/>.
        /// </summary>
        public void Create()
        {
            _directoryInfo.Create();
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Create(DirectorySecurity)"/>.
        /// </summary>
        public void Create(DirectorySecurity directorySecurity)
        {
            _directoryInfo.Create();
            _directoryInfo.SetAccessControl(directorySecurity);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#CreateSubdirectory(string)"/>.
        /// </summary>
        public IDirectoryInfo CreateSubdirectory(string path)
        {
            return FromDirectoryInfo(_directoryInfo.CreateSubdirectory(path));
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#CreateSubdirectory(string, DirectorySecurity)"/>.
        /// </summary>
        public IDirectoryInfo CreateSubdirectory(string path, DirectorySecurity directorySecurity)
        {
            var directoryInfo = CreateSubdirectory(path);
            directoryInfo.SetAccessControl(directorySecurity);
            return directoryInfo;
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Delete(bool)"/>.
        /// </summary>
        public void Delete(bool recursive)
        {
            _directoryInfo.Delete(recursive);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#EnumerateDirectories"/>.
        /// </summary>
        public IEnumerable<IDirectoryInfo> EnumerateDirectories()
        {
            return _directoryInfo.EnumerateDirectories().Select(FromDirectoryInfo);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#EnumerateDirectories(string)"/>.
        /// </summary>
        public IEnumerable<IDirectoryInfo> EnumerateDirectories(string searchPattern)
        {
            return _directoryInfo.EnumerateDirectories(searchPattern).Select(FromDirectoryInfo);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#EnumerateDirectories(string, SearchOption)"/>.
        /// </summary>
        public IEnumerable<IDirectoryInfo> EnumerateDirectories(string searchPattern, SearchOption searchOption)
        {
            return _directoryInfo.EnumerateDirectories(searchPattern, searchOption).Select(FromDirectoryInfo);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#EnumerateFiles"/>.
        /// </summary>
        public IEnumerable<IFileInfo> EnumerateFiles()
        {
            return _directoryInfo.EnumerateFiles().Select(DefaultFileInfo.FromFileInfo);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#EnumerateFiles(string)"/>.
        /// </summary>
        public IEnumerable<IFileInfo> EnumerateFiles(string searchPattern)
        {
            return _directoryInfo.EnumerateFiles(searchPattern).Select(DefaultFileInfo.FromFileInfo);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#EnumerateFiles(string, SearchOption)"/>.
        /// </summary>
        public IEnumerable<IFileInfo> EnumerateFiles(string searchPattern, SearchOption searchOption)
        {
            return _directoryInfo.EnumerateFiles(searchPattern, searchOption).Select(DefaultFileInfo.FromFileInfo);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#EnumerateFileSystemInfos"/>.
        /// </summary>
        public IEnumerable<IFileSystemInfo> EnumerateFileSystemInfos()
        {
            return ConvertFileSystemInfoEnumerable(_directoryInfo.EnumerateFileSystemInfos());
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#EnumerateFileSystemInfos(string)"/>.
        /// </summary>
        public IEnumerable<IFileSystemInfo> EnumerateFileSystemInfos(string searchPattern)
        {
            return ConvertFileSystemInfoEnumerable(_directoryInfo.EnumerateFileSystemInfos(searchPattern));
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#EnumerateFileSystemInfos(string, SearchOption)"/>.
        /// </summary>
        public IEnumerable<IFileSystemInfo> EnumerateFileSystemInfos(string searchPattern, SearchOption searchOption)
        {
            return ConvertFileSystemInfoEnumerable(_directoryInfo.EnumerateFileSystemInfos(searchPattern, searchOption));
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetAccessControl"/>.
        /// </summary>
        public DirectorySecurity GetAccessControl()
        {
            return _directoryInfo.GetAccessControl();
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetAccessControl(AccessControlSections)"/>.
        /// </summary>
        public DirectorySecurity GetAccessControl(AccessControlSections includeSections)
        {
            return _directoryInfo.GetAccessControl(includeSections);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetDirectories"/>.
        /// </summary>
        public IDirectoryInfo[] GetDirectories()
        {
            return ConvertDirectoryArray(_directoryInfo.GetDirectories());
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetDirectories(string)"/>.
        /// </summary>
        public IDirectoryInfo[] GetDirectories(string searchPattern)
        {
            return ConvertDirectoryArray(_directoryInfo.GetDirectories(searchPattern));
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetDirectories(string, SearchOption)"/>.
        /// </summary>
        public IDirectoryInfo[] GetDirectories(string searchPattern, SearchOption searchOption)
        {
            return ConvertDirectoryArray(_directoryInfo.GetDirectories(searchPattern, searchOption));
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetFiles"/>.
        /// </summary>
        public IFileInfo[] GetFiles()
        {
            return ConvertFileArray(_directoryInfo.GetFiles());
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetFiles(string)"/>.
        /// </summary>
        public IFileInfo[] GetFiles(string searchPattern)
        {
            return ConvertFileArray(_directoryInfo.GetFiles(searchPattern));
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetFiles(string, SearchOption)"/>.
        /// </summary>
        public IFileInfo[] GetFiles(string searchPattern, SearchOption searchOption)
        {
            return ConvertFileArray(_directoryInfo.GetFiles(searchPattern, searchOption));
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetFileSystemInfos"/>.
        /// </summary>
        public IFileSystemInfo[] GetFileSystemInfos()
        {
            return ConvertFileSystemInfoArray(_directoryInfo.GetFileSystemInfos());
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetFileSystemInfos(string)"/>.
        /// </summary>
        public IFileSystemInfo[] GetFileSystemInfos(string searchPattern)
        {
            return ConvertFileSystemInfoArray(_directoryInfo.GetFileSystemInfos(searchPattern));
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetFileSystemInfos(string, SearchOption)"/>.
        /// </summary>
        public IFileSystemInfo[] GetFileSystemInfos(string searchPattern, SearchOption searchOption)
        {
            return ConvertFileSystemInfoArray(_directoryInfo.GetFileSystemInfos(searchPattern, searchOption));
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#MoveTo(string)"/>.
        /// </summary>
        public void MoveTo(string destDirName)
        {
            _directoryInfo.MoveTo(destDirName);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#SetAccessControl(DirectorySecurity)"/>.
        /// </summary>
        public void SetAccessControl(DirectorySecurity directorySecurity)
        {
            _directoryInfo.SetAccessControl(directorySecurity);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#Equals(object)"/>.
        /// </summary>
        public override bool Equals(object obj)
        {
            var other = obj as DefaultDirectoryInfo;
            return other != null && Equals(other);
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#GetHashCode"/>.
        /// </summary>
        public override int GetHashCode()
        {
            return _directoryInfo != null ? _directoryInfo.GetHashCode() : 0;
        }

        /// <summary>
        /// See <see cref="DirectoryInfo#ToString"/>.
        /// </summary>
        public override string ToString()
        {
            return _directoryInfo.ToString();
        }

        private static IFileSystemInfo[] ConvertFileSystemInfoArray(IEnumerable<FileSystemInfo> fsInfos)
        {
            return ConvertFileSystemInfoEnumerable(fsInfos).ToArray();
        }

        private static IEnumerable<IFileSystemInfo> ConvertFileSystemInfoEnumerable(IEnumerable<FileSystemInfo> fileSystemInfos)
        {
            return fileSystemInfos.Select(FileSystemInfoFactory.FromFileSystemInfo).Where(fsInfo => fsInfo != null);
        }

        private static IDirectoryInfo[] ConvertDirectoryArray(DirectoryInfo[] directoryInfos)
        {
            var arr = new IDirectoryInfo[directoryInfos.Length];

            for (var i = 0; i < directoryInfos.Length; i++)
            {
                arr[i] = FromDirectoryInfo(directoryInfos[i]);
            }

            return arr;
        }

        private static IFileInfo[] ConvertFileArray(FileInfo[] fileInfos)
        {
            var arr = new IFileInfo[fileInfos.Length];

            for (var i = 0; i < fileInfos.Length; i++)
            {
                arr[i] = DefaultFileInfo.FromFileInfo(fileInfos[i]);
            }

            return arr;
        }

        private bool Equals(DefaultDirectoryInfo other)
        {
            return Equals(_directoryInfo, other._directoryInfo);
        }
    }
}