using System;
using System.Drawing;
using System.Linq;
using BS.Shared.Core;
using BeWo.Data.Access;
using BeWo.Data.Entities;

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

namespace BeWo.Service.DCEntityMapper
{
    public class InvoiceBaseDC_InvoiceBase : AbstractIDCEntityMapper<InvoiceBase, InvoiceBaseDC>
    {
        public override InvoiceBaseDC MergeWithDC(InvoiceBase pEntity, InvoiceBaseDC pDataContract)
        {
            pDataContract.InvoiceBaseOid = pEntity.Oid;
            pDataContract.InvoiceBaseVersion = pEntity.Version;

            pDataContract.SupportConceptOid = pEntity.SupportConceptOid;
            pDataContract.SenderOrganisation = pEntity.SenderOrganisation;
            pDataContract.SenderLastName = pEntity.SenderLastName;
            pDataContract.SenderFirstName = pEntity.SenderFirstName;
            pDataContract.SenderDivision = pEntity.SenderDivision;
            pDataContract.RecipientPersonOid = pEntity.RecipientPersonOid;
            pDataContract.RecipientPersonLastName = pEntity.RecipientPersonLastName;
            pDataContract.RecipientPersonFirstName = pEntity.RecipientPersonFirstName;
            pDataContract.RecipientOrganisationOid = pEntity.RecipientOrganisationOid;
            pDataContract.RecipientOrganisation = pEntity.RecipientOrganisation;
            pDataContract.RecipientDivision = pEntity.RecipientDivision;
            pDataContract.RecipientCustomerOid = pEntity.RecipientCustomerOid;
            pDataContract.RecipientCostBearerOid = pEntity.RecipientCostBearerOid;
            pDataContract.IsPaid = pEntity.IsPaid;
            pDataContract.InvoiceTitle = pEntity.InvoiceTitle;
            pDataContract.InvoiceNumber = pEntity.InvoiceNumber;
            pDataContract.InvoiceDate = pEntity.InvoiceDate;
            pDataContract.DueDate = pEntity.DueDate;
            pDataContract.CreatorLastName = pEntity.CreatorLastName;
            pDataContract.CreatorFirstName = pEntity.CreatorFirstName;
            pDataContract.AccountingPeriodEnd = pEntity.AccountingPeriodEnd;
            pDataContract.AccountingPeriodStart = pEntity.AccountingPeriodStart;
            pDataContract.CustomerReferenceNumber = pEntity.CustomerReferenceNumber;
            pDataContract.Type = pEntity.Type;
            pDataContract.Notice = pEntity.Notice;
            pDataContract.DunningLetterCount = pEntity.DunningLetterCount;
	        pDataContract.InvoiceId = pEntity.InvoiceId;
			pDataContract.InvoiceTypeText = pEntity.InvoiceTypeText;

	        if (pEntity.CostBearer2SupportConcept != null)
	        {
		        try
		        {
					pDataContract.SupportConceptCostBearerRelDc = MapperFactory
						.SupportConceptCostBearerRelDC_CostBearer2SupportConcept
						.MapToNewDC(pEntity.CostBearer2SupportConcept);
		        }
		        catch (Exception)
		        {
			        //ignore
		        }
		        
	        }
	        if (pEntity.SenderAddress != null)
            {
                pDataContract.SenderAddressOid = pEntity.SenderAddress.Oid;
                pDataContract.SenderStreet = pEntity.SenderAddress.Street;
                pDataContract.SenderTown = pEntity.SenderAddress.Town;
                pDataContract.SenderPostCode = pEntity.SenderAddress.PostalCode;
                pDataContract.SenderAddressVersion = pEntity.SenderAddress.Version;
            }

            if (pEntity.RecipientAddress != null)
            {
                pDataContract.RecipientAddressOid = pEntity.RecipientAddress.Oid;
                pDataContract.RecipientStreet = pEntity.RecipientAddress.Street;
                pDataContract.RecipientTown = pEntity.RecipientAddress.Town;
                pDataContract.RecipientPostCode = pEntity.RecipientAddress.PostalCode;
                pDataContract.RecipientAddressVersion = pEntity.RecipientAddress.Version;
            }

            pDataContract.SenderContactInformations = MapperFactory.ContactDC_Contact.MapToNewDCs(pEntity.SenderContacts);
            pDataContract.RecipientContactInformations = MapperFactory.ContactDC_Contact.MapToNewDCs(pEntity.RecipientContacts);
            pDataContract.InvoiceItems = MapperFactory.InvoiceItemDC_InvoiceItem.MapToNewDCs(pEntity.InvoiceItems);

            if (pEntity.Type == InvoiceType.Service && pEntity.Oid.HasValue)
            {
                pDataContract.TotalAmount = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(pEntity.Oid.Value).GetTotalClaim();
            }
            else if (pEntity.Type == InvoiceType.Settlement)
            {
	            //Ist eigentlich ein Fehler. Bei Spitzabrechnungen muss immer ein InvoiceItem vorhanden sein.
				//Durch einen mittlerweile behobenen Programmfehler gibt es einzelen ältere Rechnungen, bei denen das nicht so ist.
				if (!string.IsNullOrEmpty(pEntity.XMLData))
				{
					var settlementdc = Utils.XMLDeserializeFromString<SettlementDC>(pEntity.XMLData);
					pDataContract.TotalAmount = settlementdc.Claim;
				}
				else
				{
					pDataContract.TotalAmount = pDataContract.InvoiceItems.Sum(i => i.AmountTotal);
				}

            }
			else 
			{
				pDataContract.TotalAmount = pDataContract.InvoiceItems.Sum(i => i.AmountTotal);
            }

            if(pEntity.CostBearer2SupportConcept!=null)
            {
				try
				{
					pDataContract.CustomerFirstName = pEntity.CostBearer2SupportConcept.SupportConcept.Customer.Person.FirstName;
					pDataContract.CustomerLastName = pEntity.CostBearer2SupportConcept.SupportConcept.Customer.Person.LastName;
				}
				catch (Exception)
				{
					//ignore
				}
                
            }
            else if (pEntity.SupportConceptOid.HasValue)
            {
                SupportConcept sc = DAOFactory.GenericDAO.LoadByID<SupportConcept>(pEntity.SupportConceptOid.Value);
                pDataContract.CustomerFirstName = sc.Customer.Person.FirstName;
                pDataContract.CustomerLastName = sc.Customer.Person.LastName;
            }

            return pDataContract;
        }

        public override InvoiceBase MergeWithEntity(InvoiceBaseDC pDataContract, InvoiceBase pEntity)
        {
            this.ConcurrencyCheck(pDataContract.InvoiceBaseVersion, pEntity);
            pEntity.Oid = pDataContract.InvoiceBaseOid;

            pEntity.Type = pDataContract.Type;
            pEntity.SupportConceptOid = pDataContract.SupportConceptOid;
            pEntity.SenderOrganisation = pDataContract.SenderOrganisation;
            pEntity.SenderLastName = pDataContract.SenderLastName;
            pEntity.SenderFirstName = pDataContract.SenderFirstName;
            pEntity.SenderDivision = pDataContract.SenderDivision;
            pEntity.RecipientPersonOid = pDataContract.RecipientPersonOid;
            pEntity.RecipientPersonLastName = pDataContract.RecipientPersonLastName;
            pEntity.RecipientPersonFirstName = pDataContract.RecipientPersonFirstName;
            pEntity.RecipientOrganisationOid = pDataContract.RecipientOrganisationOid;
            pEntity.RecipientOrganisation = pDataContract.RecipientOrganisation;
            pEntity.RecipientDivision = pDataContract.RecipientDivision;
            pEntity.RecipientCustomerOid = pDataContract.RecipientCustomerOid;
            pEntity.RecipientCostBearerOid = pDataContract.RecipientCostBearerOid;
            pEntity.IsPaid = pDataContract.IsPaid;
            pEntity.InvoiceTitle = pDataContract.InvoiceTitle;
            pEntity.InvoiceNumber = pDataContract.InvoiceNumber;
            pEntity.InvoiceDate = pDataContract.InvoiceDate;
            pEntity.DueDate = pDataContract.DueDate;
            pEntity.CreatorLastName = pDataContract.CreatorLastName;
            pEntity.CreatorFirstName = pDataContract.CreatorFirstName;
            pEntity.AccountingPeriodEnd = pDataContract.AccountingPeriodEnd;
            pEntity.AccountingPeriodStart = pDataContract.AccountingPeriodStart;
            pEntity.CustomerReferenceNumber = pDataContract.CustomerReferenceNumber;
            pEntity.Notice = pDataContract.Notice;
            pEntity.DunningLetterCount = pDataContract.DunningLetterCount;
			pEntity.InvoiceId = pDataContract.InvoiceId;
			pEntity.InvoiceTypeText = pDataContract.InvoiceTypeText;

            if (pDataContract.ContainsSenderAddressData())
            {
                if (pEntity.SenderAddress == null)
                {
                    pEntity.SenderAddress = new Address();
                }

                this.ConcurrencyCheck(pDataContract.SenderAddressVersion, pEntity.SenderAddress);

                pEntity.SenderAddress.Oid = pDataContract.SenderAddressOid;
                pEntity.SenderAddress.Street = pDataContract.SenderStreet;
                pEntity.SenderAddress.Town = pDataContract.SenderTown;
                pEntity.SenderAddress.PostalCode = pDataContract.SenderPostCode;
            }
            else if (pEntity.SenderAddress != null)
            {
                // all-delete-orphan wird von NHibernate (noch) nicht unterstützt für many-to-one
                Address lAdress = pEntity.SenderAddress;
                pEntity.SenderAddress = null;
                DAOFactory.GenericDAO.Delete(lAdress);
            }

            if (pDataContract.ContainsRecipientAddressData())
            {
                if (pEntity.RecipientAddress == null)
                {
                    pEntity.RecipientAddress = new Address();
                }

                this.ConcurrencyCheck(pDataContract.RecipientAddressVersion, pEntity.RecipientAddress);

                pEntity.RecipientAddress.Oid = pDataContract.RecipientAddressOid;
                pEntity.RecipientAddress.Street = pDataContract.RecipientStreet;
                pEntity.RecipientAddress.Town = pDataContract.RecipientTown;
                pEntity.RecipientAddress.PostalCode = pDataContract.RecipientPostCode;
            }
            else if (pEntity.RecipientAddress != null)
            {
                // all-delete-orphan wird von NHibernate (noch) nicht unterstützt für many-to-one
                Address lInvoiceAddress = pEntity.RecipientAddress;
                pEntity.RecipientAddress = null;
                DAOFactory.GenericDAO.Delete(lInvoiceAddress);
            }

            pEntity.CostBearer2SupportConcept = null;
            if (pDataContract.SupportConceptCostBearerRelDc != null)
                pEntity.CostBearer2SupportConcept = DAOFactory.GenericDAO.LoadByID<CostBearer2SupportConcept>(pDataContract.SupportConceptCostBearerRelDc.CostBearer2SupportConceptOid.Value);

            MapperFactory.ContactDC_Contact.MergeWithEntitys(pDataContract.SenderContactInformations, pEntity.SenderContacts);
            MapperFactory.ContactDC_Contact.MergeWithEntitys(pDataContract.RecipientContactInformations, pEntity.RecipientContacts);

            MapperFactory.InvoiceItemDC_InvoiceItem.MergeWithEntitys(pDataContract.InvoiceItems, pEntity.InvoiceItems);

            return pEntity;
        }

        protected override bool AreDCAndEntityEqual(InvoiceBaseDC pDataContract, InvoiceBase pEntity)
        {
            if (pDataContract.InvoiceBaseOid == null)
            {
                return false;
            }

            return pDataContract.InvoiceBaseOid == pEntity.Oid;
        }
    }
}