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

using BeWo.Data.Access;
using BeWo.Data.Entities;

using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;

namespace BeWo.Service.DCEntityMapper
{
	public class CustomerDC_Customer : AbstractIDCEntityMapper<Customer, CustomerDC>
	{
		public override CustomerDC MergeWithDC(Customer pEntity, CustomerDC pDataContract)
		{
			MapperFactory.PersonDC_Person.MergeWithDC(pEntity.Person, pDataContract);

			pDataContract.Disabilities             = MapperFactory.ValueListEntryDC_ValueListEntry.MapToNewDCs(pEntity.ValueList.FindByType(ValueListEntryType.DisabilityType).Select(e2o => e2o.Entry));
            pDataContract.CustomerCareTypes        = MapperFactory.ValueListEntryDC_ValueListEntry.MapToNewDCs(pEntity.ValueList.FindByType(ValueListEntryType.CustomerCareType).Select(e2o => e2o.Entry));
            pDataContract.AbsenceTimes             = MapperFactory.AbsenceTimeDC_AbsenceTime.MapToNewDCs(pEntity.AbsenceTimes);
            pDataContract.RelatedEmployees         = MapperFactory.EmployeeCustomerRelDC_Employee2CustomerMapper.MapToNewDCs(pEntity.Employee2CustomerList);
            pDataContract.RelatedTeams             = MapperFactory.TeamCustomerRelDC_Team2CustomerMapper.MapToNewDCs(pEntity.Team2CustomerList);
            pDataContract.CostBearers              = MapperFactory.CustomerCostBearerRelDC_Customer2CostBearer.MapToNewDCs(pEntity.Customer2CostBearerList);
            pDataContract.EnvironmentPersons       = MapperFactory.CustomerPersonRelationDC_Customer2Person.MapToNewDCs(pEntity.Customer2PersonList);
            pDataContract.EnvironmentOrganisations = MapperFactory.CustomerOrganisationRelationDC_Customer2Organisation.MapToNewDCs(pEntity.Customer2OrganisationList);

			//if(pEntity.Jugendamt != null)
			//    pDataContract.Jugendamt = MapperFactory.CompactOrganisationDC_Organisation.MapToNewDC(pEntity.Jugendamt);

			//if (pEntity.Ansprechpartner != null)
			//    pDataContract.Ansprechpartner = MapperFactory.CompactPersonDC_Person.MapToNewDC(pEntity.Ansprechpartner);

			pDataContract.Medikamentenverordnungslisten = MapperFactory.MedikamentenverordnungslisteDC_Medikamentenverordnungsliste.MapToNewDCs(pEntity.Medikamentenverordnungslisten);
			pDataContract.DistanceInMeter               = pEntity.DistanceInMeter;
		    pDataContract.CustomerAlias                 = pEntity.CustomerAlias;
			pDataContract.Diagnosis                     = pEntity.Diagnosis;
			pDataContract.Childs                        = pEntity.Childs;
			pDataContract.EquityContribution            = pEntity.EquityContribution;
			pDataContract.ICD10Diagnosis                = pEntity.ICD10Diagnosis;
			pDataContract.Notice                        = pEntity.Notice;
			pDataContract.ReferenceNumber               = pEntity.ReferenceNumber;
			pDataContract.CustomerVersion               = pEntity.Version;
			pDataContract.CustomerOid                   = pEntity.Oid;
			pDataContract.ActivationType                = pEntity.IsActive;
            pDataContract.AssistanceBegin               = pEntity.AssistanceBegin;
			pDataContract.TerminationDate               = pEntity.TerminationDate;
			pDataContract.DebitorNumber                 = pEntity.DebitorNumber;
			pDataContract.CostCenter                    = pEntity.CostCenter;
			pDataContract.Medication                    = pEntity.Medication;
			pDataContract.Environment                   = pEntity.Environment;
			pDataContract.IsAdvisedOrAttended           = pEntity.IsAdvisedOrAttended;

			//if(pEntity.FamilyData != null)
			//{
			//    pDataContract.Kindesmutter = pEntity.FamilyData.Kindesmutter;
			//    pDataContract.Kindesvater = pEntity.FamilyData.Kindesvater;
			//    pDataContract.Geschwister = pEntity.FamilyData.Geschwister;
			//    pDataContract.Vormund = pEntity.FamilyData.Vormund;
			//    pDataContract.FamilyDataOid = pEntity.FamilyData.Oid;
			//    pDataContract.FamilyDataVersion = pEntity.FamilyData.Version;
			//}

		    pDataContract.AusstVersAmt              = pEntity.AusstVersAmt;
            pDataContract.AusweisGueltigVon         = pEntity.AusweisGueltigVon;
            pDataContract.AusweisGueltigBis         = pEntity.AusweisGueltigBis;
            pDataContract.AusweisUnbefristetGueltig = pEntity.AusweisUnbefristetGueltig;
            pDataContract.BeiblattGueltigBis        = pEntity.BeiblattGueltigBis;
            pDataContract.GradDerBehinderung        = pEntity.GradDerBehinderung;
            pDataContract.Pflegegrad                = pEntity.Pflegegrad;
            pDataContract.CustomerImage             = pEntity.CustomerImage;
		

		    if (pEntity.BehinderungsartenListe != null)
		    {
		        pDataContract.BehinderungsartenListe = pEntity.BehinderungsartenListe.ToList();
		    }

		    if (pEntity.MerkzeichenListe != null)
		    {
		        pDataContract.MerkzeichenListe = pEntity.MerkzeichenListe.ToList();
		    }

			if (pEntity.TerminationReason != null)
			{
				pDataContract.TerminationReason = MapperFactory.ValueListEntryDC_ValueListEntry.MapToNewDC(pEntity.TerminationReason);
			}

			pDataContract.PlacementList = MapperFactory.PlacementDC_Placement.MapToNewDCs(pEntity.PlacementList);

			if (pEntity.Diagnosis2CustomerList != null)
			{
				pDataContract.ICD10DiagnosisCodes = pEntity.Diagnosis2CustomerList.Select(e => e.ICD10DiagnosisCode).ToList();
			}

			IList<VarFieldDef> defs = DAOFactory.SearchDAO.GetVarFieldDefs(TableID.Customer);
			pDataContract.CustomerVarFields = MapperFactory.VarFieldDC_VarField.VarFieldMapToDCs(defs, pEntity.VarFieldValueList);

			pDataContract.AssessmentSheetCategoryDCs = MapperFactory.AssessmentSheetCategoryDC_AssessmentSheetCategory.MapToNewDCs(pEntity.AssessmentSheetCategoryList);

			return pDataContract;
		}

		public override Customer MergeWithEntity(CustomerDC pDataContract, Customer pEntity)
		{
			ConcurrencyCheck(pDataContract.CustomerVersion, pEntity);

			if (pDataContract.ContainsPersonData())
			{
				if (pEntity.Person == null)
				{
					pEntity.Person = new Person();
				}

				MapperFactory.PersonDC_Person.MergeWithEntity(pDataContract, pEntity.Person);
			}

			MapperFactory.ValueListEntryDC_ValueListEntry.MapValueEntryListBack2Entity(pDataContract.Disabilities, pEntity.ValueList, ValueListEntryType.DisabilityType, TableID.Customer, false);

			MapperFactory.ValueListEntryDC_ValueListEntry.MapValueEntryListBack2Entity(pDataContract.CustomerCareTypes, pEntity.ValueList, ValueListEntryType.CustomerCareType, TableID.Customer, false);

			MapperFactory.EmployeeCustomerRelDC_Employee2CustomerMapper.MergeWithEntitys(pDataContract.RelatedEmployees, pEntity.Employee2CustomerList);

			MapperFactory.TeamCustomerRelDC_Team2CustomerMapper.MergeWithEntitys(pDataContract.RelatedTeams, pEntity.Team2CustomerList);

			MapperFactory.CustomerCostBearerRelDC_Customer2CostBearer.MergeWithEntitys(pDataContract.CostBearers, pEntity.Customer2CostBearerList);

			MapperFactory.AbsenceTimeDC_AbsenceTime.MergeWithEntitys(pDataContract.AbsenceTimes, pEntity.AbsenceTimes);

			MapperFactory.CustomerPersonRelationDC_Customer2Person.MergeWithEntitys(pDataContract.EnvironmentPersons, pEntity.Customer2PersonList);

			MapperFactory.CustomerOrganisationRelationDC_Customer2Organisation.MergeWithEntitys(pDataContract.EnvironmentOrganisations, pEntity.Customer2OrganisationList);
			pEntity.DistanceInMeter = pDataContract.DistanceInMeter;

			MapperFactory.MedikamentenverordnungslisteDC_Medikamentenverordnungsliste.MergeWithEntitys(pDataContract.Medikamentenverordnungslisten, pEntity.Medikamentenverordnungslisten);

			//pEntity.Jugendamt = pDataContract.Jugendamt != null ? DAOFactory.GenericDAO.LoadByID<Organisation>(pDataContract.Jugendamt.OrganisationOid) : null;

			//pEntity.Ansprechpartner = pDataContract.Ansprechpartner != null ? DAOFactory.GenericDAO.LoadByID<Person>(pDataContract.Ansprechpartner.PersonOid) : null;

			
			pEntity.Diagnosis             = pDataContract.Diagnosis;
			pEntity.Medication            = pDataContract.Medication;
			pEntity.Environment           = pDataContract.Environment;
			pEntity.Childs                = pDataContract.Childs;
			pEntity.EquityContribution    = pDataContract.EquityContribution;
			pEntity.ICD10Diagnosis        = pDataContract.ICD10Diagnosis;
			pEntity.Notice                = pDataContract.Notice;
			pEntity.ReferenceNumber       = pDataContract.ReferenceNumber;
			pEntity.Oid                   = pDataContract.CustomerOid;
			pEntity.IsActive              = pDataContract.ActivationType;
		    pEntity.AssistanceBegin       = pDataContract.AssistanceBegin;
			pEntity.TerminationDate       = pDataContract.TerminationDate;
		    pEntity.CustomerAlias         = pDataContract.CustomerAlias;
			
			//if(ContainsFamilyDataData(pDataContract))
			//{
			//    ConcurrencyCheck(pDataContract.FamilyDataVersion, pEntity.FamilyData);

			//    pEntity.FamilyData.Oid = pDataContract.FamilyDataOid;
			//    pEntity.FamilyData.Kindesmutter = pDataContract.Kindesmutter;
			//    pEntity.FamilyData.Kindesvater = pDataContract.Kindesvater;
			//    pEntity.FamilyData.Geschwister = pDataContract.Geschwister;
			//    pEntity.FamilyData.Vormund = pDataContract.Vormund;
			//}
			//else if (pEntity.FamilyData != null)
			//{
			//    // all-delete-orphan wird von NHibernate (noch) nicht unterstützt für many-to-one
			//    FamilyData lFamilyData = pEntity.FamilyData;
			//    pEntity.FamilyData = null;
			//    DAOFactory.GenericDAO.Delete(lFamilyData);
			//}

		    pEntity.AusstVersAmt              = pDataContract.AusstVersAmt;
		    pEntity.AusweisGueltigVon         = pDataContract.AusweisGueltigVon;
		    pEntity.AusweisGueltigBis         = pDataContract.AusweisGueltigBis;
		    pEntity.AusweisUnbefristetGueltig = pDataContract.AusweisUnbefristetGueltig;
		    pEntity.BeiblattGueltigBis        = pDataContract.BeiblattGueltigBis;
		    pEntity.GradDerBehinderung        = pDataContract.GradDerBehinderung;
		    pEntity.BehinderungsartenListe    = pDataContract.BehinderungsartenListe;
		    pEntity.MerkzeichenListe          = pDataContract.MerkzeichenListe;
            pEntity.Pflegegrad                = pDataContract.Pflegegrad;
            pEntity.CustomerImage             = pDataContract.CustomerImage;
		    

			if (pDataContract.TerminationReason == null)
			{
				pEntity.TerminationReason = null;
			}
			else if (pEntity.TerminationReason == null || pEntity.TerminationReason.Oid != pDataContract.TerminationReason.ValueListEntryOid)
			{
				pEntity.TerminationReason = DAOFactory.GenericDAO.LoadByID<ValueListEntry>(pDataContract.TerminationReason.ValueListEntryOid.Value);
			}

			pEntity.DebitorNumber       = pDataContract.DebitorNumber;
			pEntity.CostCenter          = pDataContract.CostCenter;
			pEntity.IsAdvisedOrAttended = pDataContract.IsAdvisedOrAttended;

			MapperFactory.PlacementDC_Placement.MergeWithEntitys(pDataContract.PlacementList, pEntity.PlacementList);

			if (pDataContract.ICD10DiagnosisCodes == null || pDataContract.ICD10DiagnosisCodes.Count == 0)
			{
				pEntity.Diagnosis2CustomerList.Clear();
			}
			else
			{
				if (pEntity.Diagnosis2CustomerList == null)
				{
					pEntity.Diagnosis2CustomerList = new List<Diagnosis2Customer>();
				}

				List<Diagnosis2Customer> toDel = pEntity.Diagnosis2CustomerList.Where(e => !pDataContract.ICD10DiagnosisCodes.Contains(e.ICD10DiagnosisCode)).ToList();

				toDel.ForEach(i => pEntity.Diagnosis2CustomerList.Remove(i));

				List<string> toAdd = pDataContract.ICD10DiagnosisCodes.Where(i => pEntity.Diagnosis2CustomerList.FirstOrDefault(e => e.ICD10DiagnosisCode.Equals(i)) == null).ToList();

				toAdd.ForEach(i => pEntity.Diagnosis2CustomerList.Add(new Diagnosis2Customer {ICD10DiagnosisCode = i}));
			}

			pEntity.VarFieldValueList = MapperFactory.VarFieldDC_VarField.VarFieldMergeToEntity(pEntity.VarFieldValueList, pDataContract.CustomerVarFields, pEntity);

			pEntity.AssessmentSheetCategoryList.Clear();

			pDataContract.AssessmentSheetCategoryDCs.ForEach(
				i =>
				{
					if (i.AssessmentSheetCategoryOid.HasValue)
					{
						var original = DAOFactory.GenericDAO.LoadByID<AssessmentSheetCategory>(
							i.AssessmentSheetCategoryOid.Value);
						MapperFactory.AssessmentSheetCategoryDC_AssessmentSheetCategory.MergeWithEntity(i, original);

						pEntity.AssessmentSheetCategoryList.Add(original);
					}
					else
						pEntity.AssessmentSheetCategoryList.Add(
							MapperFactory.AssessmentSheetCategoryDC_AssessmentSheetCategory.MapToNewEntity(i));
				}
				);

			return pEntity;
		}

		public bool ContainsFamilyDataData(CustomerDC dc)
		{
			return !Utils.AreAllNullOrEmpty(dc.Kindesmutter, dc.Kindesvater, dc.Geschwister, dc.Vormund);
		}


		// private void MergeSingleTypePersonRelations(Customer2PersonType pType, CompactPersonDC pCompactPersonDC, Customer pEntity)
		// {
		// Customer2Person lP2c = pEntity.Customer2PersonList.SingleOrDefault(c2p => c2p.Type == pType);

		// // add new relation
		// if (lP2c == null && pCompactPersonDC != null)
		// {
		// lP2c = new Customer2Person();
		// lP2c.Type = pType;

		// Person lPerson = DAOFactory.GenericDAO.LoadByID<Person>(pCompactPersonDC.PersonOid);
		// lP2c.Person = MapperFactory.CompactPersonDC_Person.MergeWithEntity(pCompactPersonDC, lPerson);

		// pEntity.Customer2PersonList.Add(lP2c);
		// }
		// //remove deleted
		// else if (lP2c != null && pCompactPersonDC == null)
		// {
		// pEntity.Customer2PersonList.Remove(lP2c);
		// }
		// //merge existing
		// else if (lP2c != null && pCompactPersonDC != null)
		// {
		// Person lPerson = lP2c.Person;
		// if (lP2c.Person.Oid != pCompactPersonDC.PersonOid)
		// lPerson = DAOFactory.GenericDAO.LoadByID<Person>(pCompactPersonDC.PersonOid);

		// lP2c.Person = MapperFactory.CompactPersonDC_Person.MergeWithEntity(pCompactPersonDC, lPerson);
		// }
		// }

		protected override bool AreDCAndEntityEqual(CustomerDC pDC, Customer pEntity)
		{
			if (pDC.CustomerOid == null)
			{
				return false;
			}

			return pDC.CustomerOid == pEntity.Oid;
		}
	}
}