using System.Linq;

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

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

namespace BeWo.Service.DCEntityMapper
{
    public class OrganisationDC_Organisation : AbstractIDCEntityMapper<Organisation, OrganisationDC>
    {
        public override OrganisationDC MergeWithDC(Organisation pEntity, OrganisationDC pDataContract)
        {
            //pDataContract.RelatedPersons =
            //    MapperFactory.PersonOrganisationRelDC_Person2OrganisationMapper.MapToNewDCs(
            //        pEntity.Person2OrganisationList);

            pDataContract.OrganisationOid = pEntity.Oid;
            pDataContract.Name = pEntity.Name;
            pDataContract.OrganisationVersion = pEntity.Version;
            pDataContract.OrganisationNotice = pEntity.Notice;
            pDataContract.DebitorNumber = pEntity.DebitorNumber;
			pDataContract.ActivationType = pEntity.IsActive;

            pDataContract.RelatedPersons = MapperFactory.OrganisationPersonRelDC_Organisation2PersonMapper.MapToNewDCs(pEntity.Organisation2PersonList.Where(o2P => o2P.Person.IsActive != ActivationTypeId.Deleted));

            if (pEntity.Address != null)
            {
                pDataContract.AddressOid = pEntity.Address.Oid;
                pDataContract.Street = pEntity.Address.Street;
                pDataContract.Town = pEntity.Address.Town;
                pDataContract.PostalCode = pEntity.Address.PostalCode;
                pDataContract.AddressVersion = pEntity.Address.Version;
            }

            if (pEntity.InvoiceAddress != null)
            {
                pDataContract.InvoiceAddressOid = pEntity.InvoiceAddress.Oid;
                pDataContract.InvoiceAddressStreet = pEntity.InvoiceAddress.Street;
                pDataContract.InvoiceAddressTown = pEntity.InvoiceAddress.Town;
                pDataContract.InvoiceAddressPostalCode = pEntity.InvoiceAddress.PostalCode;
                pDataContract.InvoiceAddressVersion = pEntity.InvoiceAddress.Version;
            }

            if (pEntity.CostBearer != null)
            {
                pDataContract.CostBearerOid = pEntity.CostBearer.Oid;
                pDataContract.CostBearerVersion = pEntity.CostBearer.Version;

                pDataContract.IsSingleInvoicePerCustomer = pEntity.CostBearer.IsSingleInvoicePerCustomer;

                // pDataContract.HourlyRate = pEntity.CostBearer.HourlyRate;
                // pDataContract.RateFactor = pEntity.CostBearer.RateFactor;
                // pDataContract.MinuteIntervall = pEntity.CostBearer.MinutesIntervall;
                pDataContract.CostRatePeriods = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(pEntity.CostBearer.CostRatePeriods);
                pDataContract.IsCalculatingWithFactor = pEntity.CostBearer.IsCalculatingWithFactor;
            }

            if (pEntity.BankAccount != null)
            {
                pDataContract.BankAccountOid = pEntity.BankAccount.Oid;
                pDataContract.BankAccountVersion = pEntity.BankAccount.Version;
                pDataContract.AccountNumber = pEntity.BankAccount.AccountNumber;
                pDataContract.BankName = pEntity.BankAccount.BankName;
                pDataContract.BankCode = pEntity.BankAccount.BankCode;
                pDataContract.IBAN = pEntity.BankAccount.IBAN;
                pDataContract.Bic = pEntity.BankAccount.Bic;
            }

            pDataContract.ContactInformations = MapperFactory.ContactDC_Contact.MapToNewDCs(pEntity.Contacts);

			var defs = DAOFactory.SearchDAO.GetVarFieldDefs(TableID.Organisation);
			pDataContract.VarFields = MapperFactory.VarFieldDC_VarField.VarFieldMapToDCs(defs, pEntity.VarFieldValueList);

            return pDataContract;
        }

        public override Organisation MergeWithEntity(OrganisationDC pDataContract, Organisation pEntity)
        {
            this.ConcurrencyCheck(pDataContract.OrganisationVersion, pEntity);

            pEntity.Oid = pDataContract.OrganisationOid;
            pEntity.Name = pDataContract.Name;
            pEntity.Notice = pDataContract.OrganisationNotice;
            pEntity.DebitorNumber = pDataContract.DebitorNumber;
			pEntity.IsActive = pDataContract.ActivationType;
            //MapperFactory.OrganisationPersonRelDC_Organisation2PersonMapper.MergeWithEntitys(pDataContract.RelatedPersons, pEntity.Organisation2PersonList);

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

                this.ConcurrencyCheck(pDataContract.AddressVersion, pEntity.Address);

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

            if (pDataContract.ContainsInvoiceAddressData())
            {
                if (pEntity.InvoiceAddress == null)
                {
                    pEntity.InvoiceAddress = new Address();
                }

                this.ConcurrencyCheck(pDataContract.InvoiceAddressVersion, pEntity.InvoiceAddress);

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

            if (pDataContract.ContainsBankAccountData())
            {
                if (pEntity.BankAccount == null)
                {
                    pEntity.BankAccount = new BankAccount();
                }

                this.ConcurrencyCheck(pDataContract.BankAccountVersion, pEntity.BankAccount);

                pEntity.BankAccount.Oid = pDataContract.BankAccountOid;
                pEntity.BankAccount.Version = pDataContract.BankAccountVersion;
                pEntity.BankAccount.IBAN = pDataContract.IBAN;
                pEntity.BankAccount.Bic = pDataContract.Bic;
                pEntity.BankAccount.BankCode = pDataContract.BankCode;
                pEntity.BankAccount.BankName = pDataContract.BankName;
                pEntity.BankAccount.AccountNumber = pDataContract.AccountNumber;
            }
            else if (pEntity.BankAccount != null)
            {
                // all-delete-orphan wird von NHibernate (noch) nicht unterstützt für many-to-one)
                BankAccount lBankAccount = pEntity.BankAccount;
                pEntity.BankAccount = null;
                DAOFactory.GenericDAO.Delete(lBankAccount);
            }

            if (pDataContract.ContainsCostBearerData())
            {
                if (pEntity.CostBearer == null)
                {
                    pEntity.CostBearer = new CostBearer();
                }

                this.ConcurrencyCheck(pDataContract.CostBearerVersion, pEntity.CostBearer);

                pEntity.CostBearer.IsSingleInvoicePerCustomer = pDataContract.IsSingleInvoicePerCustomer;
                pEntity.CostBearer.Oid = pDataContract.CostBearerOid;
                pEntity.CostBearer.IsCalculatingWithFactor = pDataContract.IsCalculatingWithFactor;

                MapperFactory.CostRatePeriodDC_CostRatePeriod.MergeWithEntitys(pDataContract.CostRatePeriods.Where(c => c.CostRateValue.HasValue).ToList(), pEntity.CostBearer.CostRatePeriods);
                foreach (var costRatePeriod in pEntity.CostBearer.CostRatePeriods)
                {
                    costRatePeriod.ObjectTid = TableID.CostBearer;
                }
            }
            else if (pEntity.CostBearer != null)
            {
                // all-delete-orphan wird von NHibernate (noch) nicht unterstützt für many-to-one)
                CostBearer lCostBearer = pEntity.CostBearer;
                pEntity.CostBearer = null;
                DAOFactory.GenericDAO.Delete(lCostBearer);
            }

            MapperFactory.ContactDC_Contact.MergeWithEntitys(pDataContract.ContactInformations, pEntity.Contacts);

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

            return pEntity;
        }

        protected override bool AreDCAndEntityEqual(OrganisationDC pDC, Organisation pEntity)
        {
            if (pDC.OrganisationOid == null)
            {
                return false;
            }

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