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

using Model.Entities.Base;
using Model.Entities.Files;
using Model.Entities.Files.FS_Entities;
using Model.Entities.Files.Repo;
using Model.Entities.Users;

namespace Model.UnitsOfWork
{
    public class UOW : IDisposable
    {
        public readonly Context context;

        public readonly Repo_SRootDirectory Repo_SRootDirectory;
        public readonly Repo_SDirectory Repo_SDirectory;
        public readonly Repo_SFile Repo_SFile;
        public readonly Repo_SFileUpload Repo_SFileUpload;
        public IQueryable<FS_Item> FS_Items => context.FS_Items;

        public readonly Repo_User Repo_User;
        public readonly Repo_Group Repo_Group;



        public UOW()
        {
            context = new Context();

            Repo_Group = new Repo_Group(this);
            Repo_User = new Repo_User(this);

            Repo_SRootDirectory = new Repo_SRootDirectory(this);
            Repo_SDirectory = new Repo_SDirectory(this);
            Repo_SFile = new Repo_SFile(this);
            Repo_SFileUpload = new Repo_SFileUpload(this);            
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="clear">Удалить базу</param>
        private UOW(bool clear)
        {
            context = new Context(clear);

            Repo_Group = new Repo_Group(this);
            Repo_User = new Repo_User(this);

            Repo_SRootDirectory = new Repo_SRootDirectory(this);
            Repo_SDirectory = new Repo_SDirectory(this);
            Repo_SFile = new Repo_SFile(this);
            Repo_SFileUpload = new Repo_SFileUpload(this);            
        }




        public FS_Item Create(FS_Item elem)
        {
            switch (elem.Type)
            {
                case Enum_BaseDirectoryEntity.File:
                    return Repo_SFile.Create((SFile)elem);
                case Enum_BaseDirectoryEntity.Directory:
                    return Repo_SDirectory.Create((SDirectory)elem);
                case Enum_BaseDirectoryEntity.RootDirectory:
                    return Repo_SRootDirectory.Create((SRootDirectory)elem);
                case Enum_BaseDirectoryEntity.UploadFile:
                    return Repo_SFileUpload.Create((SFileUpload)elem);
                default:
                    throw new Exception();
            }
        }
        public void Update(FS_Item elem)
        {
            switch (elem.Type)
            {
                case Enum_BaseDirectoryEntity.File:
                    Repo_SFile.Update((SFile)elem);
                    return;
                case Enum_BaseDirectoryEntity.Directory:
                    Repo_SDirectory.Update((SDirectory)elem);
                    return;
                case Enum_BaseDirectoryEntity.RootDirectory:
                    Repo_SRootDirectory.Update((SRootDirectory)elem);
                    return;
                case Enum_BaseDirectoryEntity.UploadFile:
                    Repo_SFileUpload.Update((SFileUpload)elem);
                    return;
                default:
                    throw new Exception();
            }
        }
        public void Delete(FS_Item elem)
        {
            switch (elem.Type)
            {
                case Enum_BaseDirectoryEntity.File:
                    Repo_SFile.Delete((SFile)elem);
                    return;
                case Enum_BaseDirectoryEntity.Directory:
                    Repo_SDirectory.Delete((SDirectory)elem);
                    return;
                case Enum_BaseDirectoryEntity.RootDirectory:
                    Repo_SRootDirectory.Delete((SRootDirectory)elem);
                    return;
                case Enum_BaseDirectoryEntity.UploadFile:
                    Repo_SFileUpload.Delete((SFileUpload)elem);
                    return;
                default:
                    throw new Exception();
            }
        }



        /// <summary>
        /// Выполняет иницилизацию приложения при старте (1 раз)
        /// </summary>
        /// <param name="Clear">Удалить базу</param>
        /// <returns></returns>
        public static UOW InitRepo(bool Clear)
        {
            var uow = new UOW(Clear);

            uow.Repo_Group.RepoInit();
            uow.Repo_User.RepoInit();

            uow.Repo_SRootDirectory.RepoInit();
            uow.Repo_SDirectory.RepoInit();
            uow.Repo_SFile.RepoInit();
            uow.Repo_SFileUpload.RepoInit();

            return uow;
        }


        #region Dispose

        //Flag: Has Dispose already been called?
        bool disposed = false;

        // Public implementation of Dispose pattern callable by consumers.
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // Protected implementation of Dispose pattern.
        /// <summary>
        /// Структура:
        /// disposing ? (Освобождаем управляемые ресурсы); 
        /// (освобождаем неуправляемые объекты)
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
                return;

            if (disposing)
            {
                context.Dispose();
            }

            disposed = true;
        }

        ~UOW()
        {
            Dispose(false);
        }

        #endregion
    }
}
