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

using System.Data.Entity;

using BLL.Base;
using BLL.Services.System;
using Model.Entities.Users;
using Model.UnitsOfWork;
using Model.ViewModel;
using Model.ViewModel.Edit;

namespace BLL.Services.Mapper
{
    public class UserMapper : BaseServices
    {
        readonly PermissionServices permissionServices;

        public UserMapper(UOW UOW, PermissionServices permissionServices) : base(UOW) { this.permissionServices = permissionServices; }


        /// <summary>
        /// DB -> Edit
        /// Модель для редактирования пользователей
        /// </summary>
        /// <returns></returns>
        public List<EditUserModel> GetEdit_User()
        {
            var users = UOW.Repo_User.All_NoTrack.
                Include(e => e.Groups).ToList();
            var groups = UOW.Repo_Group.All_NoTrack_List.
                Where(e => e.Name != EnumDefaultGroups.Анонимные.ToString());

            return users.Select(e => new EditUserModel()
            {
                ID = e.ID,
                Name = e.Login,
                Password = "",
                Changes = EnumChanges.NoChange,
                Active = e.IsActive,
                Groups = groups.Select(e2 => new InfoGroupModel()
                {
                    ID = e2.ID,
                    Name = e2.Name,
                    EnterInGroup = e.Groups.
                        FirstOrDefault(e3 => e3.ID == e2.ID) != null
                }).ToList()
            }).ToList();
        }

        /// <summary>
        /// Edit -> DB
        /// Преобразование Edit в db Entitites
        /// </summary>
        /// <param name="editGroup"></param>
        /// <returns></returns>
        public List<(EditUserModel Edited, User DBUser)> GetEntities_User(List<EditUserModel> editUsers)
        {
            List<(EditUserModel Edited, User DBUser)> res = new List<(EditUserModel Edited, User DBUser)>(editUsers.Count());
            var groups = UOW.Repo_Group.All_List;

            foreach (var elem in editUsers)
            {
                var current_groups_id = elem.Groups.
                    Where(g => g.EnterInGroup).
                    Select(g => g.ID);

                User current_user = null;

                switch (elem.Changes)
                {
                    case EnumChanges.Create:
                        current_user = new User(elem.Name, elem.Password, elem.Active,
                            groups.Where(e => current_groups_id.Contains(e.ID)));
                        break;
                    case EnumChanges.Update:
                        current_user = UOW.Repo_User.All.
                            FirstOrDefault(e => e.ID == elem.ID);
                        current_user.Login = elem.Name;
                        current_user.Password = string.IsNullOrEmpty(elem.Password)
                            ? current_user.Password
                            : elem.Password;
                        current_user.IsActive = elem.Active;
                        current_user.Groups = new List<Group>(groups.
                            Where(e => current_groups_id.Contains(e.ID)));
                        break;
                    case EnumChanges.Delete:
                        current_user = UOW.Repo_User.All.
                            FirstOrDefault(e => e.ID == elem.ID);
                        break;
                }

                res.Add(new ValueTuple<EditUserModel, User>(elem, current_user));
            }

            return res;
        }


        /// <summary>
        /// Db -> Info
        /// </summary>
        /// <param name="user">db user</param>
        /// <param name="WithPassword">Прикрепить пароль</param>
        /// <param name="WithPermission">Прикрепить права на RootDirs</param>
        /// <returns></returns>
        public UserInfoModel GetInfo_User(User user, bool WithPassword = false, bool WithPermission = false)
        {
            var RootDirs = UOW.Repo_SRootDirectory.All_NoTrack_List;

            return new UserInfoModel()
            {
                Login = user.Login,
                Password = WithPassword
                ? user.Password
                : "",
                IsAdmin = user.IsAdmin,
                RootDirs = WithPermission
                ? RootDirs.Select(e => new InfoRootDirModel()
                {
                    ID = e.ID,
                    Name = e.Name,
                    CanDownload = permissionServices.CanDownload(user, e),
                    CanOpen = permissionServices.CanOpen(user, e),
                    CanUpload = permissionServices.CanUpload(user, e)
                }
                ).ToList()
                : new List<InfoRootDirModel>()
            };
        }

    }
}
