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

using System.IO;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using BLL.Services;
using BLL.Services.System;
using BLL.Services.FS;
using Model.Tools;
using Model.UnitsOfWork;
using Model.Entities.Users;
using Model.Entities.Files.FS_Entities;

namespace AppTests
{
    [TestClass]
    public class Test_UOW
    {

        protected DirectoryInfo GetProjectPath()
        {
            return new DirectoryInfo(Assembly.GetExecutingAssembly().Location)
                .Parent
                .Parent
                .Parent;
        }
        protected DirectoryInfo GetSolutionPath()
        {
            return GetProjectPath().Parent;
        }
        protected DirectoryInfo GetWebProjectPath()
        {
            return new DirectoryInfo(GetSolutionPath().FullName + "\\Web");
        }


        protected User GetAdmin(UOW UOW)
        {
            return UOW.Repo_User
                .All.FirstOrDefault(e => e.Login == "Admin");
        }
        protected SRootDirectory GetTestDir(UOW UOW)
        {
            string TestDirName = "ForTests";

            return UOW.Repo_SRootDirectory
                    .All.FirstOrDefault(e => e.Name == TestDirName);
        }


        /// <summary>
        /// Проверка установки соединения с базой
        /// </summary>
        [TestMethod]
        public void DropAndInit()
        {
            var Config = ConfigTools.Get();
            //Расположение конфигурации
            Config.ConfigDirectory = GetWebProjectPath().FullName;//Server.MapPath("~/");
            Config.Import();

            //Очистить базу данных
            //Проинициализирвоать базу
            using (var UOW = Model.UnitsOfWork.UOW.InitRepo(true))
            {
                //Прочитать корневые папки
                new ConfigurationServices(UOW, Config).ReadConfiguration();
                //Просканировать все папки
                Task.WaitAll(new ScanServices(UOW).ScanAllDirs());
            }
        }

        /// <summary>
        /// Проверка пользователя по умолчанию
        /// </summary>
        [TestMethod]
        public void TestDefaultUsers()
        {
            using (var UOW = new UOW())
            {
                if (GetAdmin(UOW) == null)
                    throw new Exception("Admin user not found");
            }
        }


        /// <summary>
        /// Проверка групп по умолчанию
        /// </summary>
        [TestMethod]
        public void TestDefaultGroups()
        {
            using (var UOW = new UOW())
            {
                var groups = UOW.Repo_Group.All_List;

                Repo_Group.DefaultGroupsNames
                    .ToList().ForEach(e1 => 
                    {
                        if (groups.FirstOrDefault(e2 => e2.Name == e1) == null)
                            throw new Exception("Default group " + e1 + " not found");
                    });
            }
        }


        /// <summary>
        /// Проверка наличия в базе информации о папке для тестов
        /// Также очищает все соержимое тестовой папки
        /// </summary>
        [TestMethod]
        public void TestDirectory()
        {           

            using (var UOW = new UOW())
            {
                var TestDir = GetTestDir(UOW);
                if (TestDir == null)
                    throw new Exception("Test dir not found");

                if (!TestDir.Info.Exists)
                    throw new Exception("Test Directory not exists");

                //Очистка папки
                var items = TestDir.Items.ToList();
                items.ForEach(e => UOW.Delete(e));
            }
        }


        /// <summary>
        /// Тест имитирующий использование серсира для загрузки файла
        /// В конце удаляет загруженный файл
        /// </summary>
        [TestMethod]
        public void UploadTest()
        {
            //Данные файла
            string Data = "DataToFile";
            
            byte[] data_byte;

            using (MemoryStream ms = new MemoryStream())
            {
                using (StreamWriter sw = new StreamWriter(ms))
                {
                    sw.WriteLine(Data);
                    sw.Flush();

                    ms.Position = 0;
                    data_byte = ms.ToArray();
                }
            }

            string FileName = "UploadTest.txt";

            using (var UOW = new UOW())
            {
                var Admin = GetAdmin(UOW);
                var TestDir = GetTestDir(UOW);
                

                UploadServices uploadServices = 
                    new UploadServices(UOW);

                var upload_project = uploadServices
                    .StartUpload(TestDir, FileName, data_byte.Length, Admin);

                int start = 0;
                int stop = upload_project.NextChunkSize;
                bool Uploaded  = false;

                while (!Uploaded)
                {
                    var cur_block = data_byte.Skip(start).Take(stop - start)
                        .ToArray();

                    Uploaded = uploadServices.UploadChunk(upload_project, cur_block);
                    start = stop;
                    stop += upload_project.NextChunkSize;
                }

                var uploaded_file = TestDir
                    .Files.FirstOrDefault(e => e.Name == FileName);

                if (uploaded_file == null)
                    throw new Exception("Uploaded file not found");

                if (!uploaded_file.Info.Exists)
                    throw new Exception("Uploaded file not exist in FS");

                //Удаление загруженного файла
                UOW.Delete(uploaded_file);
            }
        }

    }
}
