using System;
using System.Security;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Xml;

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

using BS.Shared.Extensions;

namespace BeWo.Service.Security
{
    public class SecurityContextInitializer : ICallContextInitializer
    {
        public void AfterInvoke(object pCorrelationState)
        {
            if (pCorrelationState is LoggedInUserOperationContextExt)
            {
                OperationContext.Current.Extensions.Remove((LoggedInUserOperationContextExt)pCorrelationState);
            }
        }

        public object BeforeInvoke(InstanceContext pInstanceContext, IClientChannel pChannel, Message pMessage)
        {
            try
            {
                var lTemp = pMessage.Headers.Action.Split("/");
                string lServiceName = lTemp[lTemp.Count - 1];
                string lServiceInterface = lTemp[lTemp.Count - 2];

                // TODO Hier kann man jetzt etwas bauen wer sich für welchen service autorisieren muss...
                if (lServiceName == "IsUserValid" || lServiceName == "ResetTenant" || lServiceName == "ResetAllTenants" || lServiceName == "GetEmailForUserName")
                {
                    return null;
                }

                string lUserName = null, lPassword = null;

                int lSecurityHeaderIndex = pMessage.Headers.FindHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

                if (lSecurityHeaderIndex > -1)
                {
                    XmlReader lReader = pMessage.Headers.GetReaderAtHeader(lSecurityHeaderIndex);

                    if (lReader.ReadToFollowing("Username"))
                    {
                        lUserName = lReader.ReadString();
                    }

                    if (lReader.ReadToFollowing("Password"))
                    {
                        lPassword = lReader.ReadString();
                    }

                    ApplicationUser lUser = DAOFactory.UserDAO.FindUserByLoginName(lUserName);

                    if (lUser != null && DAOFactory.UserDAO.CheckPassword(lUser, lPassword))
                    {
                        var lExt = new LoggedInUserOperationContextExt { User = lUser, LoginName = lUserName, UnhashedPassword = lPassword };
                        OperationContext.Current.Extensions.Add(lExt);
                        return lExt;
                    }
                }

                throw new SecurityException("Nicht autorisiert");
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }
    }
}