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

using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.DCEntityMapper;

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

namespace BeWo.Service.Plugins
{
	public class CustomerService : AbstractIDSpecificDefaultClass<CustomerService>
	{
		protected virtual bool FetchTeams()
		{
			return true;
		}

		public virtual List<CompactCustomerDC> GetAllActiveAndArchivedCustomersCompact(long currentEmployeeOid)
		{
			IEnumerable<Customer> customers = DAOFactory.SearchDAO.GetAllActiveAndArchivedCustomersWithRelatedEmployee();

			var result = new List<CompactCustomerDC>();
			var cProcessed = new Dictionary<long, bool>();
			var teamOids = new Dictionary<long, long>();

			if (FetchTeams())
			{
				var teams = DAOFactory.SearchDAO.FindTeamsOfEmployee(currentEmployeeOid);
				var teams2 = DAOFactory.SearchDAO.FindLeadingTeams(currentEmployeeOid);


				foreach (var t in teams)
				{
					if (!teamOids.ContainsKey(t.Oid.Value))
					{
						teamOids.Add(t.Oid.Value, t.Oid.Value);
					}
				}
				foreach (var t in teams2)
				{
					if (!teamOids.ContainsKey(t.Oid.Value))
					{
						teamOids.Add(t.Oid.Value, t.Oid.Value);
					}
				}
			}
			foreach (Customer customer in customers)
			{
				if (!cProcessed.ContainsKey(customer.Oid.Value))
				{
					CompactCustomerDC dc = CreateCompactCustomerDCWithEmployeeRelation(customer, false, true, currentEmployeeOid, teamOids);

					result.Add(dc);

					cProcessed.Add(customer.Oid.Value, true);
				}
			}

			return result;
		}

		public virtual List<CompactCustomerDC> GetAllActiveCustomersCompact(bool fetchReferenceNumbers, long? currentEmployeeOid)
		{
			IEnumerable<Customer> customers = DAOFactory.SearchDAO.GetAllActiveCustomersWithAddress();

			var teamOids = new Dictionary<long, long>();

			if (FetchTeams() && currentEmployeeOid.HasValue)
			{
				var teams = DAOFactory.SearchDAO.FindTeamsOfEmployee(currentEmployeeOid.Value);
				var teams2 = DAOFactory.SearchDAO.FindLeadingTeams(currentEmployeeOid.Value);

				foreach (var t in teams)
				{
					if (!teamOids.ContainsKey(t.Oid.Value))
					{
						teamOids.Add(t.Oid.Value, t.Oid.Value);
					}
				}
				foreach (var t in teams2)
				{
					if (!teamOids.ContainsKey(t.Oid.Value))
					{
						teamOids.Add(t.Oid.Value, t.Oid.Value);
					}
				}
			}

			return customers.Select(customer => CreateCompactCustomerDCWithEmployeeRelation(customer, fetchReferenceNumbers, false, currentEmployeeOid, teamOids)).ToList();
		}

		public virtual List<CompactCustomerDC> GetAllCustomersCompact(bool fetchReferenceNumbers, long? currentEmployeeOid)
		{
			var result = new List<CompactCustomerDC>();

			var cProcessed = new Dictionary<long, bool>();
			var customers = DAOFactory.SearchDAO.GetAllCustomersWithRelatedEmployee();

			var teamOids = new Dictionary<long, long>();

			if (FetchTeams() && currentEmployeeOid.HasValue)
			{
				var teams = DAOFactory.SearchDAO.FindTeamsOfEmployee(currentEmployeeOid.Value);
				var teams2 = DAOFactory.SearchDAO.FindLeadingTeams(currentEmployeeOid.Value);

				foreach (var t in teams)
				{
					if (!teamOids.ContainsKey(t.Oid.Value))
					{
						teamOids.Add(t.Oid.Value, t.Oid.Value);
					}
				}
				foreach (var t in teams2)
				{
					if (!teamOids.ContainsKey(t.Oid.Value))
					{
						teamOids.Add(t.Oid.Value, t.Oid.Value);
					}
				}
			}

			foreach (Customer customer in customers)
			{
				if (!cProcessed.ContainsKey(customer.Oid.Value))
				{
					CompactCustomerDC dc = CreateCompactCustomerDCWithEmployeeRelation(customer, fetchReferenceNumbers, true, currentEmployeeOid, teamOids);

					result.Add(dc);

					cProcessed.Add(customer.Oid.Value, true);
				}
			}

			return result;
		}

		//public virtual List<CompactCustomerDC> GetAllCustomersCompact(bool fetchReferenceNumbers, long? currentEmployeeOid)
		//{
		//	var customers = DAOFactory.SearchDAO.GetAllCustomersWithAddress();
		//	var teamOids = new Dictionary<long, long>();

		//	if (FetchTeams() && currentEmployeeOid.HasValue)
		//	{
		//		var teams = DAOFactory.SearchDAO.FindTeamsOfEmployee(currentEmployeeOid.Value);
		//		var teams2 = DAOFactory.SearchDAO.FindLeadingTeams(currentEmployeeOid.Value);

		//		foreach (var t in teams)
		//		{
		//			if (!teamOids.ContainsKey(t.Oid.Value))
		//			{
		//				teamOids.Add(t.Oid.Value, t.Oid.Value);
		//			}
		//		}
		//		foreach (var t in teams2)
		//		{
		//			if (!teamOids.ContainsKey(t.Oid.Value))
		//			{
		//				teamOids.Add(t.Oid.Value, t.Oid.Value);
		//			}
		//		}
		//	}

		//	return customers.Select(customer => CreateCompactCustomerDCWithEmployeeRelation(customer, fetchReferenceNumbers, false, currentEmployeeOid, teamOids)).ToList();
		//}

		protected CompactCustomerDC CreateCompactCustomerDCWithEmployeeRelation(Customer pEntity, bool fetchReferenceNumbers, bool fetchEmployees, long? currentEmployeeOid, Dictionary<long, long> teamOids)
		{
			
			var dc = new CompactCustomerDC();

			dc.CustomerOid = pEntity.Oid.Value;
			dc.CustomerVersion = pEntity.Version.Value;
			dc.FirstName = pEntity.Person.FirstName;
			dc.LastName = pEntity.Person.LastName;
			dc.DateOfBirth = pEntity.Person.DateOfBirth;
			dc.ActivationType = pEntity.IsActive;
			dc.TerminationDate = pEntity.TerminationDate;
			dc.Sex = pEntity.Person.Sex;
			dc.AbsenceTimes = MapperFactory.AbsenceTimeDC_AbsenceTime.MapToNewDCs(pEntity.AbsenceTimes);
		    dc.CustomerAlias = pEntity.CustomerAlias;

			if (pEntity.Person.Address != null)
			{
				dc.Street = pEntity.Person.Address.Street;
				dc.PostalCode = pEntity.Person.Address.PostalCode;
				dc.Town = pEntity.Person.Address.Town;
			}

			if (fetchReferenceNumbers)
			{
				pEntity.Customer2CostBearerList.DoForEach(c2cb => dc.CostBearerReferenceNumbers[c2cb.CostBearer.Oid.Value] = c2cb.ReferenceNumber);
			}

			if (currentEmployeeOid != null)
			{
				foreach (Employee2Customer e2c in pEntity.Employee2CustomerList)
				{
					if (!dc.IsRelatedToEmployee)
					{
						if (currentEmployeeOid == e2c.EmployeeOid.Value)
						{
							dc.IsRelatedToEmployee = true;
						}
					}
				}

				if (!dc.IsRelatedToEmployee && teamOids != null && teamOids.Count > 0)
				{


					foreach (var t2c in pEntity.Team2CustomerList)
					{
						if (!dc.IsRelatedToEmployee)
						{
							if (teamOids.ContainsKey(t2c.TeamOid.Value))
							{
								dc.IsRelatedToEmployee = true;
							}
						}
					}
				}

			}

			if (fetchEmployees)
			{
				foreach (Employee2Customer e2c in pEntity.Employee2CustomerList)
				{
					foreach (ValueListEntry2Object vle2o in e2c.ValueList)
					{
						ValueListEntry vle = vle2o.Entry;
						if (vle.SystemEntryID != null && vle.SystemEntryID.Value == SystemEntryID.EmployeeRoleMainAttendant && e2c.EmployeeOid != currentEmployeeOid.Value)
						{
							string empName = e2c.Employee.Person.FirstName + " " + e2c.Employee.Person.LastName;
							if (String.IsNullOrEmpty(dc.MainAttendant))
								dc.MainAttendant = vle.Value + ": " + empName;
							else
							{
								if (!dc.MainAttendant.Contains(empName))
								{
									if (dc.MainAttendant.Contains(vle.Value))
										dc.MainAttendant += ", " + empName;
									else
										dc.MainAttendant += ", " + vle.Value + ": " + empName;
								}
							}
						}

						if (currentEmployeeOid != null && e2c.EmployeeOid == currentEmployeeOid.Value)
						{
							dc.CurrentEmployeeRole = vle.Value;
						}
					}
				}
			}

			return dc;
		}
	}
}