using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;

using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.Core;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Security;
using BeWo.Service.ServiceContracts;

using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;

using NHibernate;

namespace BeWo.Service.ServiceImplementations
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
    public class EmployeeServiceImp : IEmployeeService
    {
        public void ArchiveEmployee(long pOid, long pVersion)
        {
            try
            {
                var e = DAOFactory.GenericDAO.LoadByID<Employee>(pOid);
                e.Person.IsActive = ActivationTypeId.Archived;

                ServiceLogic.SetActivationType<Employee>(pOid, pVersion, ActivationTypeId.Archived);

            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateAssessmentSheetCategories(List<AssessmentSheetCategoryDC> dcs)
        {
            try
            {
                ServiceLogic.SetActivationType<AssessmentSheetCategory>(dcs.ToDictionary(i => i.AssessmentSheetCategoryOid.Value, i => i.AssessmentSheetCategoryVersion.Value), ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateAssessmentSheetEntries(List<AssessmentSheetEntryDC> dcs)
        {
            try
            {
                //ServiceLogic.SetActivationType<AssessmentSheetEntry>(dcs.ToDictionary(i => i.AssessmentSheetEntryOid.Value, i => i.AssessmentSheetEntryVersion.Value), ActivationTypeId.Deleted);
                var entries = DAOFactory.GenericDAO.LoadByIDs<AssessmentSheetEntry>(dcs.Select(i => i.AssessmentSheetEntryOid.Value)).Where(e => e.SystemEntryID == null);

                //entries.DoForEach(or => MapperFactory.AssessmentSheetEntryDC_AssessmentSheetEntry.ConcurrencyCheck(pOid2Version[or.Oid.Value], or));
                DAOFactory.GenericDAO.Delete(entries);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateAssessmentSheetValues(List<AssessmentSheetValueDC> dcs)
        {
            try
            {
                ServiceLogic.SetActivationType<AssessmentSheetValue>(dcs.ToDictionary(i => i.AssessmentSheetValueOid.Value, i => i.AssessmentSheetValueVersion.Value), ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateEmployee(long pOid, long pVersion)
        {
            try
            {
                var e = DAOFactory.GenericDAO.LoadByID<Employee>(pOid);
                e.Person.IsActive = ActivationTypeId.Deleted;
                ServiceLogic.SetActivationType<Employee>(pOid, pVersion, ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateEmployees(Dictionary<long, long> pOid2Version)
        {
            try
            {
                ServiceLogic.SetActivationType<Employee>(pOid2Version, ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateNewsItems(List<NewsItemDC> dcs)
        {
            try
            {
                ServiceLogic.SetActivationType<NewsItem>(dcs.ToDictionary(i => i.NewsItemOid.Value, i => i.NewsItemVersion.Value), ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateTeam(long pOid, long pVersion)
        {
            try
            {
                ServiceLogic.SetActivationType<Team>(pOid, pVersion, ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateTeams(Dictionary<long, long> pOid2Version)
        {
            try
            {
                ServiceLogic.SetActivationType<Team>(pOid2Version, ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeleteEmployee(long pOid, long pVersion)
        {
            try
            {
                this.DeleteEmployees(new Dictionary<long, long> { { pOid, pVersion } });
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeleteEmployeeCustomerRelation(long pOid, long pVersion)
        {
            try
            {
                this.DeleteEmployeeCustomerRelations(new Dictionary<long, long> { { pOid, pVersion } });
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeleteEmployeeCustomerRelations(Dictionary<long, long> pOid2Version)
        {
            try
            {
                var lOriginals = DAOFactory.GenericDAO.LoadByIDs<Employee2Customer>(pOid2Version.Select(e => e.Key));
                lOriginals.DoForEach(or => MapperFactory.EmployeeCustomerRelDC_Employee2CustomerMapper.ConcurrencyCheck(pOid2Version[or.Oid.Value], or));

                DAOFactory.GenericDAO.Delete(lOriginals);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeleteEmployees(Dictionary<long, long> pOid2Version)
        {
            try
            {
                pOid2Version.Keys.DoForEach(SettingsLogic.RemoveFromAllHistories<Employee>);
                var lOriginals = DAOFactory.GenericDAO.LoadByIDs<Employee>(pOid2Version.Select(e => e.Key));
                lOriginals.DoForEach(or => MapperFactory.EmployeeDC_Employee.ConcurrencyCheck(pOid2Version[or.Oid.Value], or));

                DAOFactory.GenericDAO.Delete(lOriginals);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactEmployeeDC> FindEmployee(string pFirstName, string pLastName, string pPersonnelNumber)
        {
            try
            {
                return MapperFactory.CompactEmployeeDC_Employee.MapToNewDCs(DAOFactory.SearchDAO.FindEmployee(pFirstName, pLastName, pPersonnelNumber));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactTeamDC> FindTeams(string pTeamName, string pLeaderFirstName, string pLeaderLastName)
        {
            try
            {
                return MapperFactory.CompactTeamDC_Team.MapToNewDCs(DAOFactory.SearchDAO.FindTeams(pTeamName, pLeaderFirstName, pLeaderLastName));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactEmployeeDC> GetAllActiveAndArchivedEmployeesCompact()
        {
            try
            {
                return MapperFactory.CompactEmployeeDC_Employee.MapToNewDCs(DAOFactory.GenericDAO.GetAllActiveAndArchived<Employee>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactEmployeeDC> GetAllActiveEmployeesCompact()
        {
            try
            {
                return MapperFactory.CompactEmployeeDC_Employee.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<Employee>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactEmployeeDC> GetAllTeamMember(CompactEmployeeDC employee)
        {
            try
            {
                Dictionary<long, bool> inTeamDict = new Dictionary<long, bool>();
                List<Employee> teamMember = new List<Employee>();
                var teams = DAOFactory.GenericDAO.GetAllActive<Team>();
                foreach (var team in teams)
                {
                    bool contained = false;
                    foreach (var e in team.MemberList)
                    {
                        if ((team.Leader != null && team.Leader.Oid == employee.EmployeeOid) || e.Oid.Value.Equals(employee.EmployeeOid))
                            contained = true;
                    }    
                    if (contained)
                    {
                        foreach (var e in team.MemberList)
                        {
                            if (!inTeamDict.ContainsKey(e.Oid.Value))
                            {
                                teamMember.Add(e);
                                inTeamDict.Add(e.Oid.Value, true);
                            }
                        } 
                    }
                }
                

                var dcList = MapperFactory.CompactEmployeeDC_Employee.MapToNewDCs(teamMember);
                if (!inTeamDict.ContainsKey(employee.EmployeeOid))
                    dcList.Add(employee);
                return dcList;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<EmploymentTypeDC> GetAllEmploymentTypes()
        {
            try
            {
                return MapperFactory.EmploymentTypeDC_EmploymentType.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<EmploymentType>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<long> InsertNewEmploymentTypes(List<EmploymentTypeDC> pEntries)
        {
            try
            {
                var lEntities = MapperFactory.EmploymentTypeDC_EmploymentType.MapToNewEntities(pEntries);
                DAOFactory.GenericDAO.Insert(lEntities);
                return lEntities.Select(e => e.Oid.Value).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void UpdateEmploymentTypes(List<EmploymentTypeDC> pEntries)
        {
            try
            {
                var lOriginals = DAOFactory.GenericDAO.LoadByIDs<EmploymentType>(pEntries.Select(en => en.EmploymentTypeOid.Value));
                MapperFactory.EmploymentTypeDC_EmploymentType.MergeWithEntitys(pEntries, lOriginals);
                DAOFactory.GenericDAO.Update(lOriginals);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateEmploymentTypes(Dictionary<long, long> pOid2Version)
        {
            try
            {
                ServiceLogic.SetActivationType<EmploymentType>(pOid2Version, ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<AssessmentSheetCategoryDC> GetAllAssessmentSheetCategories()
        {
            try
            {
                return MapperFactory.AssessmentSheetCategoryDC_AssessmentSheetCategory.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<AssessmentSheetCategory>().Where(cat => !cat.ScopeType.HasValue || cat.ScopeType.Value == ScopeTypeId.Global));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<AssessmentSheetEntryDC> GetAllAssessmentSheetEntries()
        {
            try
            {
                return MapperFactory.AssessmentSheetEntryDC_AssessmentSheetEntry.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<AssessmentSheetEntry>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<AssessmentSheetValueDC> GetAllAssessmentSheetValues()
        {
            try
            {
                return MapperFactory.AssessmentSheetValueDC_AssessmentSheetValue.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<AssessmentSheetValue>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<EmployeeDC> GetAllEmployees()
        {
            try
            {
                return DAOFactory.GenericDAO.GetAll<Employee>().Select(emp => MapperFactory.EmployeeDC_Employee.MapToNewDC(emp)).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<NewsItemDC> GetAllNewsItems()
        {
            try
            {
                return MapperFactory.NewsItemDC_NewsItem.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<NewsItem>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactTeamDC> GetAllTeamsCompact()
        {
            try
            {
                return MapperFactory.CompactTeamDC_Team.MapToNewDCs(DAOFactory.GenericDAO.GetAllActive<Team>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }
        
        public List<AssessmentSheetEntryDC> GetAssessmentSheetEntriesForCustomer(long customerOid, DateTime startDt, DateTime endDt)
        {
            

            try
            {
                return MapperFactory.AssessmentSheetEntryDC_AssessmentSheetEntry.MapToNewDCs(DAOFactory.SearchDAO.GetAssessmentSheetEntriesForCustomer(customerOid, startDt, endDt));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public EmployeeDC GetEmployeeWithPersonOid(long pPersonOid)
        {
            try
            {
                return MapperFactory.EmployeeDC_Employee.MapToNewDC(DAOFactory.SearchDAO.FindEmployeeWithPersonOid(pPersonOid));
            }
            catch (Exception)
            {
                throw new FaultException<BeWoFault>(new BeWoFault(String.Format("Mitarbeiter mit Id {0} wurde nicht gefunden!", pPersonOid)));
            }
        }

        public List<CompactEmployeeDC> GetLastOpenedEmployees()
        {
            try
            {
                return MapperFactory.CompactEmployeeDC_Employee.MapToNewDCs(SettingsLogic.GetLastOpened<Employee>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactTeamDC> GetLastOpenedTeams()
        {
            try
            {
                return MapperFactory.CompactTeamDC_Team.MapToNewDCs(SettingsLogic.GetLastOpened<Team>());
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<NewsItemDC> GetPublishedNewsItems()
        {
            try
            {
                return this.GetAllNewsItems().Where(i => i.PublishDate.HasValue && i.PublishDate.Value.Date <= DateTime.Now).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

		public List<NewsItemDC> GetPublishedNewsItemsForEmployee(long employeeOid, bool fetchTeamNews)
		{
			try
			{
				IList<long> teamOids = new List<long>();
				var allItems = DAOFactory.GenericDAO.GetAllActive<NewsItem>();

				if (fetchTeamNews)
				{
					var teams = DAOFactory.SearchDAO.FindTeamsOfEmployee(employeeOid);
					var leadingTeams = DAOFactory.SearchDAO.FindLeadingTeams(employeeOid);
					if (teams != null)
					{
						teamOids = teams.Select(t => t.Oid.Value).ToList();

					}
					if (leadingTeams != null)
					{
						teamOids.AddRange(leadingTeams.Select(t => t.Oid.Value));

					}
				}
				teamOids = teamOids.Distinct().ToList();
				var items =
						allItems.Where(
							i =>
							{
								if (!i.TeamOid.HasValue)
								{
									return i.PublishDate.HasValue && i.PublishDate.Value.Date <= DateTime.Now;
								}
								return teamOids.Contains(i.TeamOid.Value);
								
							}).ToList();

				var dcList = MapperFactory.NewsItemDC_NewsItem.MapToNewDCs(items);
				List<NewsItemDC> newDcList = new List<NewsItemDC>();
				if (fetchTeamNews)
				{
					foreach (var teamOid in teamOids)
					{
						if (dcList.Count(i => i.Team != null && i.Team.TeamOid == teamOid) == 0)
						{
							Team t = DAOFactory.GenericDAO.LoadByID<Team>(teamOid);
							NewsItemDC newDc = new NewsItemDC();
							newDc.Team = new CompactTeamDC();
							newDc.Team.Name = t.Name;
							newDc.Team.TeamOid = t.Oid.Value;
							newDc.Team.TeamVersion = t.Version.Value;

							newDcList.Add(newDc);
						}
					}
				}
				dcList.AddRange(newDcList);
				
				return dcList.OrderByDescending(i => i.PublishDate).ToList();

			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteNewsItem(long pOid, long pVersion)
		{
			try
			{
				var original = DAOFactory.GenericDAO.LoadByID<NewsItem>(pOid);

				MapperFactory.NewsItemDC_NewsItem.ConcurrencyCheck(pVersion, original);

				DAOFactory.GenericDAO.Delete(original);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public long InsertNewNewsItem(NewsItemDC dc)
		{
			return InsertNewNewsItems(new List<NewsItemDC>{dc}).FirstOrDefault();

		}

		public long UpdateNewsItem(NewsItemDC dc)
		{
			try
			{
				var lOrigial = DAOFactory.GenericDAO.LoadByID<NewsItem>(dc.NewsItemOid.Value);
				MapperFactory.NewsItemDC_NewsItem.MergeWithEntity(dc, lOrigial);
				DAOFactory.GenericDAO.Update(lOrigial);
				return lOrigial.Oid.Value;
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

        public void InsertEmployeeCustomerRelation(CustomerEmployeeRelationDC pRelationDC)
        {
            try
            {
                DAOFactory.GenericDAO.Insert(MapperFactory.EmployeeCustomerRelDC_Employee2CustomerMapper.MapToNewEntity(pRelationDC));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<long> InsertNewAssessmentSheetCategories(List<AssessmentSheetCategoryDC> dcs)
        {
            try
            {
                var newAssessmentSheetCategories = MapperFactory.AssessmentSheetCategoryDC_AssessmentSheetCategory.MapToNewEntities(dcs);
                DAOFactory.GenericDAO.Insert(newAssessmentSheetCategories);
                return newAssessmentSheetCategories.Select(i => i.Oid.Value).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<long> InsertNewAssessmentSheetEntries(List<AssessmentSheetEntryDC> dcs)
        {
            try
            {
                var newAssessmentSheetEntries = MapperFactory.AssessmentSheetEntryDC_AssessmentSheetEntry.MapToNewEntities(dcs);
                DAOFactory.GenericDAO.Insert(newAssessmentSheetEntries);
                return newAssessmentSheetEntries.Select(i => i.Oid.Value).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<long> InsertNewAssessmentSheetValues(List<AssessmentSheetValueDC> dcs)
        {
            try
            {
                var newAssessmentSheetValues = MapperFactory.AssessmentSheetValueDC_AssessmentSheetValue.MapToNewEntities(dcs);
                DAOFactory.GenericDAO.Insert(newAssessmentSheetValues);
                return newAssessmentSheetValues.Select(i => i.Oid.Value).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long InsertNewEmployee(EmployeeDC pEmployeeDC)
        {
            try
            {
				var li = SecurityUtils.GetLicenseInfo();
				if (li.EmployeeCount >= li.MaxEmployeeCount)
				{
					return -1;
				}
                Employee lEmployee = MapperFactory.EmployeeDC_Employee.MapToNewEntity(pEmployeeDC);
                DAOFactory.GenericDAO.Insert(lEmployee);
                return lEmployee.Oid.Value;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<long> InsertNewNewsItems(List<NewsItemDC> dcs)
        {
            try
            {
                var newNewsItems = MapperFactory.NewsItemDC_NewsItem.MapToNewEntities(dcs);
                DAOFactory.GenericDAO.Insert(newNewsItems);
                return newNewsItems.Select(i => i.Oid.Value).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long InsertNewTeam(TeamDC pTeam)
        {
            try
            {
                Team lTeam = MapperFactory.TeamDC_Team.MapToNewEntity(pTeam);
                DAOFactory.GenericDAO.Insert(lTeam);
                return lTeam.Oid.Value;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public TeamDC LoadTeam(long pTeamOid)
        {
            try
            {
                SettingsLogic.AddToUsersHistory<Team>(pTeamOid);
                return MapperFactory.TeamDC_Team.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Team>(pTeamOid));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public CompactTeamDC LoadCompactTeam(long pTeamOid)
        {
            try
            {
                SettingsLogic.AddToUsersHistory<Team>(pTeamOid);
                return MapperFactory.CompactTeamDC_Team.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Team>(pTeamOid));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public EmployeeDC LoadLoggedOnEmployee(long pEmployeeOid)
        {
            try
            {
                return MapperFactory.EmployeeDC_Employee.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Employee>(pEmployeeOid));
            }
            catch (Exception e)
            {
                throw new FaultException<BeWoFault>(new BeWoFault(e), e.Message);
            }
        }

        public EmployeeDC LoadEmployee(long pEmployeeOid)
        {
            try
            {
                SettingsLogic.AddToUsersHistory<Employee>(pEmployeeOid);
                return MapperFactory.EmployeeDC_Employee.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Employee>(pEmployeeOid));
            }
            catch (Exception e)
            {
                throw new FaultException<BeWoFault>(new BeWoFault(e), e.Message);
            }
        }

        public CompactEmployeeDC LoadCompactEmployee(long pEmployeeOid)
        {
            try
            {
                SettingsLogic.AddToUsersHistory<Employee>(pEmployeeOid);
                return MapperFactory.CompactEmployeeDC_Employee.MapToNewDC(DAOFactory.GenericDAO.LoadByID<Employee>(pEmployeeOid));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void UpdateAssessmentSheetCategories(List<AssessmentSheetCategoryDC> dcs)
        {
            try
            {
                var originals = DAOFactory.GenericDAO.LoadByIDs<AssessmentSheetCategory>(dcs.Select(i => i.AssessmentSheetCategoryOid.Value));
                MapperFactory.AssessmentSheetCategoryDC_AssessmentSheetCategory.MergeWithEntitys(dcs, originals);
                DAOFactory.GenericDAO.Update(originals);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void UpdateAssessmentSheetEntries(List<AssessmentSheetEntryDC> dcs)
        {
            try
            {
                var originals = DAOFactory.GenericDAO.LoadByIDs<AssessmentSheetEntry>(dcs.Select(i => i.AssessmentSheetEntryOid.Value));

                var aSCategories = DAOFactory.GenericDAO.GetAll<AssessmentSheetCategory>().Where(c => c.SystemEntryID.Equals(SystemEntryID.AdditionalServiceAssessmentSheet));

				List<AssessmentSheetEntry> removeList = new List<AssessmentSheetEntry>();
	            foreach (var ase in originals)
	            {

					if (ase.SystemEntryID.Equals(SystemEntryID.AdditionalServiceAssessmentSheet) &&
						aSCategories.Count(c => c.Description.Equals(ase.AssessmentSheetCategory.Description)) > 0)
                    {
                        removeList.Add(ase);
                    }
                }
	            foreach (var ase in removeList)
	            {
		            originals.Remove(ase);
	            }
	            if (originals.Count > 0)
	            {
		            MapperFactory.AssessmentSheetEntryDC_AssessmentSheetEntry.MergeWithEntitys(dcs, originals);

					if (originals.Count > 0)
						DAOFactory.GenericDAO.Update(originals);
	            }
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void UpdateAssessmentSheetValues(List<AssessmentSheetValueDC> dcs)
        {
            try
            {
                var originals = DAOFactory.GenericDAO.LoadByIDs<AssessmentSheetValue>(dcs.Select(i => i.AssessmentSheetValueOid.Value));
                MapperFactory.AssessmentSheetValueDC_AssessmentSheetValue.MergeWithEntitys(dcs, originals);
                DAOFactory.GenericDAO.Update(originals);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long UpdateEmployee(EmployeeDC pEmployeeDC)
        {
            try
            {
                var lOriginal = DAOFactory.GenericDAO.LoadByID<Employee>(pEmployeeDC.EmployeeOid.Value);
                MapperFactory.EmployeeDC_Employee.MergeWithEntity(pEmployeeDC, lOriginal);
                DAOFactory.GenericDAO.Update(lOriginal);
                return lOriginal.Oid.Value;
            }
            catch (StaleObjectStateException)
            {
                throw new FaultException<BeWoFault>(new BeWoFault("Wurde in der Zwischenzeit geändert", BeWoFaultType.Concurrency));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void UpdateNewsItems(List<NewsItemDC> dcs)
        {
            try
            {
                var originals = DAOFactory.GenericDAO.LoadByIDs<NewsItem>(dcs.Select(i => i.NewsItemOid.Value));
                MapperFactory.NewsItemDC_NewsItem.MergeWithEntitys(dcs, originals);
                DAOFactory.GenericDAO.Update(originals);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long UpdateTeam(TeamDC pTeam)
        {
            try
            {
                Team lOriginal = DAOFactory.GenericDAO.LoadByID<Team>(pTeam.TeamOid.Value);
                MapperFactory.TeamDC_Team.MergeWithEntity(pTeam, lOriginal);
                DAOFactory.GenericDAO.Update(lOriginal);
                return lOriginal.Oid.Value;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<AbsenceTimeDC> GetAllEmployeeAbsenceTimes()
        {
            try
            {
                return MapperFactory.AbsenceTimeDC_AbsenceTime.MapToNewDCs(DAOFactory.SearchDAO.FindAbsenceTimes(true, false));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public void DeactivateGroupOfPeople(long pOid, long pVersion)
        {
            try
            {
                ServiceLogic.SetActivationType<GroupOfPeople>(pOid, pVersion, ActivationTypeId.Deleted);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long InsertNewGroupOfPeople(GroupOfPeopleDC pGroupOfPeople)
        {
            try
            {
                GroupOfPeople obj = MapperFactory.GroupOfPeopleDC_GroupOfPeople.MapToNewEntity(pGroupOfPeople);
                DAOFactory.GenericDAO.Insert(obj);
                return obj.Oid.Value;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public GroupOfPeopleDC LoadGroupOfPeople(long pOid)
        {
            try
            {
                return MapperFactory.GroupOfPeopleDC_GroupOfPeople.MapToNewDC(DAOFactory.GenericDAO.LoadByID<GroupOfPeople>(pOid));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public long UpdateGroupOfPeople(GroupOfPeopleDC pGroupOfPeople)
        {
            try
            {
                GroupOfPeople lOriginal = DAOFactory.GenericDAO.LoadByID<GroupOfPeople>(pGroupOfPeople.GroupOfPeopleOid.Value);
                MapperFactory.GroupOfPeopleDC_GroupOfPeople.MergeWithEntity(pGroupOfPeople, lOriginal);
                DAOFactory.GenericDAO.Update(lOriginal);
                return lOriginal.Oid.Value;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactGroupOfPeopleDC> GetAllGroupsCompact(long? employeeOid)
        {
            try
            {
                var groups = GetAllGroupsContainingMemberOfEmployee(employeeOid);

                return MapperFactory.CompactGroupOfPeopleDC_GroupOfPeople.MapToNewDCs(groups);

            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<GroupOfPeopleDC> GetAllGroups(long? employeeOid)
        {
            try
            {
                var groups = GetAllGroupsContainingMemberOfEmployee(employeeOid);

                return MapperFactory.GroupOfPeopleDC_GroupOfPeople.MapToNewDCs(groups);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        private IEnumerable<GroupOfPeople> GetAllGroupsContainingMemberOfEmployee(long? employeeOid)
        {
            var allgroups = DAOFactory.GenericDAO.GetAllActive<GroupOfPeople>();
            if (!employeeOid.HasValue)
                return allgroups;
            var groups = new List<GroupOfPeople>();
            Dictionary<long, bool> processedGroups = new Dictionary<long, bool>();
            Employee emp = DAOFactory.GenericDAO.LoadByID<Employee>(employeeOid.Value);

            foreach (var groupOfPeople in allgroups)
            {
                if (!processedGroups.ContainsKey(groupOfPeople.Oid.Value))
                {
                    processedGroups.Add(groupOfPeople.Oid.Value, true);
                    if (employeeOid.Value == groupOfPeople.CreatedByEmployeeOid || ContainsMemberOfEmployee(groupOfPeople, emp))
                        groups.Add(groupOfPeople);
                }
            }
            return groups;
            
        }

        private bool ContainsMemberOfEmployee(GroupOfPeople groupOfPeople, Employee emp)
        {
            return groupOfPeople.CostBearer2SupportConceptList.Any(c2s => emp.Employee2CustomerList.Any(e2c => e2c.CustomerOid == c2s.SupportConcept.Customer.Oid));
        }

        public bool IsAssessmentSheetEntryBelongingToAS(long assessmentSheetCategoryOid)
        {
            var cat = DAOFactory.GenericDAO.GetByID<AssessmentSheetCategory>(assessmentSheetCategoryOid);

            return cat.SystemEntryID.Equals(SystemEntryID.AdditionalServiceAssessmentSheet);
        }

        public bool IsAssessmentSheetCategoryBelongingToAS(long assessmentSheetCategoryOid)
        {
            try
            {
                var category = DAOFactory.GenericDAO.GetByID<AssessmentSheetCategory>(assessmentSheetCategoryOid);

                return category.SystemEntryID.Equals(SystemEntryID.AdditionalServiceAssessmentSheet);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

		public List<OvertimeDC> GetAllOvertimesFromEmployee(long employeeOid)
	    {
			try
			{
				var allOvertimes = DAOFactory.GenericDAO.GetAll<Overtime>();
				var overtimes = allOvertimes.Where(o => o.EmployeeOid.Equals(employeeOid));

				return MapperFactory.OvertimeDC_Overtime.MapToNewDCs(overtimes);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
	    }

		public List<OvertimeDC> GetAllOvertimes()
		{
			try
			{
				var allOvertimes = DAOFactory.GenericDAO.GetAll<Overtime>();
				return MapperFactory.OvertimeDC_Overtime.MapToNewDCs(allOvertimes);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteOvertimes(Dictionary<long, long> pOid2Version)
	    {
			try
			{
				pOid2Version.Keys.DoForEach(SettingsLogic.RemoveFromAllHistories<Overtime>);
				var lOriginals = DAOFactory.GenericDAO.LoadByIDs<Overtime>(pOid2Version.Select(e => e.Key));
				lOriginals.DoForEach(or => MapperFactory.OvertimeDC_Overtime.ConcurrencyCheck(pOid2Version[or.Oid.Value], or));

				DAOFactory.GenericDAO.Delete(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
	    }

		public List<long> InsertOvertimes(List<OvertimeDC> pOvertimes)
	    {
			try
			{
				var newOvertimes = MapperFactory.OvertimeDC_Overtime.MapToNewEntities(pOvertimes);
				DAOFactory.GenericDAO.Insert(newOvertimes);

				return newOvertimes.Select(i => i.Oid.Value).ToList();
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
	    }

	    public List<long> UpdateOvertimes(List<OvertimeDC> pOvertimes)
	    {
			try
			{
				var pOids = (from motherfucker in pOvertimes where motherfucker.OvertimeOid.HasValue select motherfucker.OvertimeOid.Value).ToList();
				var lOriginals = DAOFactory.GenericDAO.LoadByIDs<Overtime>(pOids);

				MapperFactory.OvertimeDC_Overtime.MergeWithEntitys(pOvertimes, lOriginals);
				DAOFactory.GenericDAO.Update(lOriginals);

				return (from mumu in lOriginals where mumu.Oid.HasValue select mumu.Oid.Value).ToList();
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
	    }

	    public List<AuszahlungsartDC> GetAllAuszahlungsarten()
	    {
			try
			{
				var alleAuszahlungsarten = DAOFactory.GenericDAO.GetAll<Auszahlungsart>();

				return MapperFactory.AuszahlungsartDC_Auszahlungsart.MapToNewDCs(alleAuszahlungsarten);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
	    }

	    public List<long> InsertAuszahlungsarten(IEnumerable<AuszahlungsartDC> pAuszahlungsarten)
	    {
			try
			{
				var neueAuszahlungsarten = MapperFactory.AuszahlungsartDC_Auszahlungsart.MapToNewEntities(pAuszahlungsarten);
				DAOFactory.GenericDAO.Insert(neueAuszahlungsarten);

				return neueAuszahlungsarten.Select(i => i.Oid.Value).ToList();
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
	    }

		public List<long> UpdateAuszahlungsarten(List<AuszahlungsartDC> pAuszahlungsarten)
		{
			try
			{
				var pOids = (from motherfucker in pAuszahlungsarten where motherfucker.AuszahlungsartOid.HasValue select motherfucker.AuszahlungsartOid.Value).ToList();
				var lOriginals = DAOFactory.GenericDAO.LoadByIDs<Auszahlungsart>(pOids);

				MapperFactory.AuszahlungsartDC_Auszahlungsart.MergeWithEntitys(pAuszahlungsarten, lOriginals);
				DAOFactory.GenericDAO.Update(lOriginals);

				return (from mumu in lOriginals where mumu.Oid.HasValue select mumu.Oid.Value).ToList();
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

		public void DeleteAuszahlungsarten(Dictionary<long, long> pOid2Version)
		{
			try
			{
				pOid2Version.Keys.DoForEach(SettingsLogic.RemoveFromAllHistories<Auszahlungsart>);
				var lOriginals = DAOFactory.GenericDAO.LoadByIDs<Auszahlungsart>(pOid2Version.Select(e => e.Key));
				lOriginals.DoForEach(or => MapperFactory.AuszahlungsartDC_Auszahlungsart.ConcurrencyCheck(pOid2Version[or.Oid.Value], or));

				DAOFactory.GenericDAO.Delete(lOriginals);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
		}

	    public List<CompactTeamDC> GetTeamOidsByEmployee(long pEmployeeOid)
	    {
			try
			{
				var liste = DAOFactory.SearchDAO.FindTeamsOfEmployee(pEmployeeOid);
				return MapperFactory.CompactTeamDC_Team.MapToNewDCs(liste);
			}
			catch (Exception e)
			{
				throw Utils.CreateBeWoFaultException(e);
			}
	    }



        public List<CompactEmployeeDC> GetAllChatActiveEmployeesCompact()
        {
            try
            {
                var employees = DAOFactory.SearchDAO.FindAllChatActiveEmployees();

                return MapperFactory.CompactEmployeeDC_Employee.MapToNewDCs(employees);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<EmployeeAPPCodeDC> GetAllEmployeeAppCodes(long pEmployeeOid)
        {

            var liste = DAOFactory.SearchDAO.FindAllEmployeeAppCodes(pEmployeeOid);


            return MapperFactory.EmployeeAPPCodeDC_EmployeeAPPCode.MapToNewDCs(liste);

        }




    }
}