using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GreenTree.Nachtragsmanagement.Core.Data;
using GreenTree.Nachtragsmanagement.Core.Domain.User;

namespace GreenTree.Nachtragsmanagement.Services.User
{
    /// <summary>
    /// User service
    /// </summary>
    public class UserService : IUserService
    {
        #region Fields

        private readonly IRepository<Core.Domain.User.User> _userRepository;
        private readonly IRepository<Role> _roleRepository;
        private readonly IRepository<Function> _functionRepository;

        #endregion

        #region Ctor

        /// <summary>
        /// Initializes a new instance of the UserService class
        /// </summary>
        public UserService(
            IRepository<Core.Domain.User.User> userRepository,
            IRepository<Role> roleRepository,
            IRepository<Function> functionRepository)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _functionRepository = functionRepository;
        }

        #endregion

        #region User

        /// <summary>
        /// Gets all users
        /// </summary>
        public IList<Core.Domain.User.User> GetAllUsers()
        {
            return _userRepository.Table.ToList();
        }

        /// <summary>
        /// Gets a user by specified Id
        /// </summary>
        /// <param name="id">User identifier.</param>
        public Core.Domain.User.User GetUserById(int id)
        {
            return _userRepository.GetById(id);
        }

        /// <summary>
        /// Gets all users to the specified ids
        /// </summary>
        public IList<Core.Domain.User.User> GetUsersByIds(int[] ids)
        {
            return _userRepository.Table
                .Where(u => ids.Contains(u.Id))
                .ToList();
        }

        /// <summary>
        /// Gets a user by specified custom number
        /// </summary>
        /// <param name="customNumber">Customer number.</param>
        public Core.Domain.User.User GetUserByCustomNumber(string customNumber)
        {
            return _userRepository
                .Table.FirstOrDefault(u => u.CustomNumber == customNumber);
        }

        /// <summary>
        /// Insert a user
        /// </summary>
        /// <param name="user">User.</param>
        public void InsertUser(Core.Domain.User.User user)
        {
            _userRepository.Insert(user);
        }

        /// <summary>
        /// Update a user
        /// </summary>
        /// <param name="user">User.</param>
        public void UpdateUser(Core.Domain.User.User user)
        {
            _userRepository.Update(user);
        }

        /// <summary>
        /// Delete a user
        /// </summary>
        /// <param name="user">User.</param>
        public void DeleteUser(Core.Domain.User.User user)
        {
            _userRepository.Delete(user);
        }

        #endregion

        #region Role

        /// <summary>
        /// Gets all roles
        /// </summary>
        public IList<Role> GetAllRoles()
        {
            return _roleRepository.Table.ToList();
        }

        /// <summary>
        /// Gets a role by specified Id
        /// </summary>
        /// <param name="id">Role identifier.</param>
        public Role GetRoleById(int id)
        {
            return _roleRepository.GetById(id);
        }

        /// <summary>
        /// Gets all roles to the specified ids
        /// </summary>
        public IList<Role> GetRolesByIds(int[] ids)
        {
            return _roleRepository.Table
                .Where(r => ids.Contains(r.Id))
                .ToList();
        }

        /// <summary>
        /// Gets all users to the corresponding role
        /// </summary>
        /// <param name="roleId">Role id.</param>
        public IList<Core.Domain.User.User> GetUsersByRole(int roleId)
        {
            return _userRepository.Table
                .Where(u => u.Roles
                    .Select(r => r.Id)
                    .Contains(roleId))
                .ToList();
        }

        /// <summary>
        /// Insert a user
        /// </summary>
        /// <param name="role">Role.</param>
        public void InsertRole(Role role)
        {
            _roleRepository.Insert(role);
        }

        /// <summary>
        /// Update a role
        /// </summary>
        /// <param name="role">Role.</param>
        public void UpdateRole(Role role)
        {
            _roleRepository.Update(role);
        }

        /// <summary>
        /// Delete a role
        /// </summary>
        /// <param name="role">Role.</param>
        public void DeleteRole(Role role)
        {
            _roleRepository.Delete(role);
        }

        #endregion

        #region Function

        /// <summary>
        /// Gets all functions
        /// </summary>
        public IList<Function> GetAllFunctions()
        {
            return _functionRepository.Table.ToList();
        }

        /// <summary>
        /// Gets a function by specified Id
        /// </summary>
        /// <param name="id">Function identifier.</param>
        public Function GetFunctionById(int id)
        {
            return _functionRepository.GetById(id);
        }

        /// <summary>
        /// Gets a function by specified name
        /// </summary>
        /// <param name="name">Function name.</param>
        public Function GetFunctionByName(string name)
        {
            return
                _functionRepository.Table
                    .FirstOrDefault(f => f.Name == name);
        }

        /// <summary>
        /// Gets all functions to the specified ids
        /// </summary>
        public IList<Function> GetFunctionsByIds(int[] ids)
        {
            return _functionRepository.Table
                .Where(f => ids.Contains(f.Id))
                .ToList();
        }

        /// <summary>
        /// Insert a function
        /// </summary>
        /// <param name="function">Function.</param>
        public void InsertFunction(Function function)
        {
            _functionRepository.Insert(function);
        }

        /// <summary>
        /// Update a function
        /// </summary>
        /// <param name="function">Function.</param>
        public void UpdateFunction(Function function)
        {
            _functionRepository.Update(function);
        }

        /// <summary>
        /// Delete a function
        /// </summary>
        /// <param name="function">Function.</param>
        public void DeleteFunction(Function function)
        {
            _functionRepository.Delete(function);
        }

        #endregion
    }
}