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

using System.IO;

using Model.Entities.Base;
using Model.Entities.Files.FS_Entities;
using Model.UnitsOfWork;

namespace Model.Entities.Files.Repo
{
    public class Repo_SFileUpload : Base_FS_Repository<SFileUpload>
    {

        public Repo_SFileUpload(UOW UOW) : base(UOW, Enum_BaseDirectoryEntity.UploadFile) { }

        protected override void Validation_Create(SFileUpload elem)
        {
            if (string.IsNullOrEmpty(elem.Name))
                throw Repo_Exception<SFileUpload>.Factory(this, elem, Repo_Exceptions.Name_is_null_or_empty);

            if (elem.Parent == null)
                throw Repo_Exception<SFileUpload>.Factory(this, elem, Repo_Exceptions.Parent_is_null);

            if (elem.Parent.ContainsName(elem))
                throw Repo_Exception<SFileUpload>.Factory(this, elem, Repo_Exceptions.Name_already_exists_in_parents);

            try
            {
                new FileStream(elem.Info.FullName, FileMode.CreateNew).Close();
            }
            catch (Exception ex)
            {
                throw new Repo_Exception<SFileUpload>(this, elem, "CreateFile inner ex", ex);
            }
        }

        protected override void Validation_Update(SFileUpload old, SFileUpload elem)
        {
            if (old.Info.FullName != elem.Info.FullName)
                throw Repo_Exception<SFileUpload>.Factory(this, elem, Repo_Exceptions.Name_cant_change);

            if (!elem.Info.Exists)
                throw Repo_Exception<SFileUpload>.Factory(this, elem, Repo_Exceptions.File_not_found);

            if (elem.Info.Length != elem.UploadedSize)
                throw Repo_Exception<SFileUpload>.Factory(this, elem, Repo_Exceptions.Size_not_equils);

            //Система нескольких попыток доступа к файлу
            for (int i = 3; i > -1; i--)
            {
                try
                {

                    using (var stream = new FileStream(elem.Info.FullName, FileMode.Append, FileAccess.Write))
                    {
                        using (BinaryWriter wr = new BinaryWriter(stream))
                        {
                            wr.Write(elem.CurrentChunk);
                        }
                    }

                    break;
                }
                catch (Exception ex)
                {
                    if (i == 0)
                        throw ex;

                    System.Threading.Thread.Sleep(100);
                }
            }

            elem.UploadedSize += elem.NextChunkSize;
        }

        protected override void Validation_Delete(SFileUpload elem)
        {
            File.Delete(elem.PhysicalPath);
        }

        
    }
}
