/*
 * Copyright  1999-2004 The Apache Software Foundation.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package org.apache.savan.eventing;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.util.UUIDGenerator;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.addressing.EndpointReferenceHelper;
import org.apache.axis2.databinding.types.Duration;
import org.apache.axis2.databinding.utils.ConverterUtil;
import org.apache.savan.SavanConstants;
import org.apache.savan.SavanException;
import org.apache.savan.SavanMessageContext;
import org.apache.savan.configuration.ConfigurationManager;
import org.apache.savan.configuration.Protocol;
import org.apache.savan.configuration.SubscriberBean;
import org.apache.savan.eventing.subscribers.EventingSubscriber;
import org.apache.savan.filters.Filter;
import org.apache.savan.subscribers.Subscriber;
import org.apache.savan.subscription.ExpirationBean;
import org.apache.savan.subscription.SubscriptionProcessor;
import org.apache.savan.util.CommonUtil;
import org.apache.savan.util.UtilFactory;

import javax.xml.namespace.QName;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Calendar;
import java.util.Date;

public class EventingSubscriptionProcessor extends SubscriptionProcessor {

    public void init(SavanMessageContext smc) throws SavanException {
        //setting the subscriber_id as a property if possible.

        String id = getSubscriberID(smc);
        if (id != null) {
            smc.setProperty(EventingConstants.TransferedProperties.SUBSCRIBER_UUID, id);
        }
    }

    public Subscriber getSubscriberFromMessage(SavanMessageContext smc) throws SavanException {

        ConfigurationManager configurationManager = (ConfigurationManager)smc
                .getConfigurationContext().getProperty(SavanConstants.CONFIGURATION_MANAGER);
        if (configurationManager == null)
            throw new SavanException("Configuration Manager not set");

        Protocol protocol = smc.getProtocol();
        if (protocol == null)
            throw new SavanException("Protocol not found");

        UtilFactory utilFactory = protocol.getUtilFactory();

        SOAPEnvelope envelope = smc.getEnvelope();
        if (envelope == null)
            return null;

//		AbstractSubscriber subscriber = utilFactory.createSubscriber();  //eventing only works on leaf subscriber for now.

        String subscriberName = protocol.getDefaultSubscriber();
        SubscriberBean subscriberBean = configurationManager.getSubscriberBean(subscriberName);

        Subscriber subscriber = configurationManager.getSubscriberInstance(subscriberName);

        if (!(subscriber instanceof EventingSubscriber)) {
            String message =
                    "Eventing protocol only support implementations of eventing subscriber as Subscribers";
            throw new SavanException(message);
        }

        EventingSubscriber eventingSubscriber = (EventingSubscriber)subscriber;
        String id = UUIDGenerator.getUUID();
        smc.setProperty(EventingConstants.TransferedProperties.SUBSCRIBER_UUID, id);
        try {
            URI uri = new URI(id);
            eventingSubscriber.setId(uri);
        } catch (URISyntaxException e) {
            throw new SavanException(e);
        }

        SOAPBody body = envelope.getBody();
        OMElement subscribeElement = body.getFirstChildWithName(new QName(
                EventingConstants.EVENTING_NAMESPACE, EventingConstants.ElementNames.Subscribe));
        if (subscribeElement == null)
            throw new SavanException("'Subscribe' element is not present");

        OMElement endToElement = subscribeElement.getFirstChildWithName(new QName(
                EventingConstants.EVENTING_NAMESPACE, EventingConstants.ElementNames.EndTo));
        if (endToElement != null) {
            EndpointReference endToEPR = null;

            try {
                endToEPR = EndpointReferenceHelper.fromOM(endToElement);
            }
            catch (AxisFault af) {
                throw new SavanException(af);
            }

            eventingSubscriber.setEndToEPr(endToEPR);
        }

        OMElement deliveryElement = subscribeElement.getFirstChildWithName(new QName(
                EventingConstants.EVENTING_NAMESPACE, EventingConstants.ElementNames.Delivery));
        if (deliveryElement == null)
            throw new SavanException("Delivery element is not present");

        OMElement notifyToElement = deliveryElement.getFirstChildWithName(new QName(
                EventingConstants.EVENTING_NAMESPACE, EventingConstants.ElementNames.NotifyTo));
        if (notifyToElement == null)
            throw new SavanException("NotifyTo element is null");

        EndpointReference notifyToEPr = null;

        try {
            notifyToEPr = EndpointReferenceHelper.fromOM(notifyToElement);
        }
        catch (AxisFault af) {
            throw new SavanException(af);
        }

        OMAttribute deliveryModeAttr =
                deliveryElement.getAttribute(new QName(EventingConstants.ElementNames.Mode));
        String deliveryMode = null;
        if (deliveryModeAttr != null) {
            deliveryMode = deliveryModeAttr.getAttributeValue().trim();
        } else {
            deliveryMode = EventingConstants.DEFAULT_DELIVERY_MODE;
        }

        if (!deliveryModesupported()) {
            //TODO throw unsupported delivery mode fault.
        }

        Delivery delivery = new Delivery();
        delivery.setDeliveryEPR(notifyToEPr);
        delivery.setDeliveryMode(deliveryMode);

        eventingSubscriber.setDelivery(delivery);

        OMElement expiresElement =
                subscribeElement.getFirstChildWithName(EventingConstants.EXPIRES_QNAME);
        if (expiresElement != null) {
            String expiresText = expiresElement.getText();

            if (expiresText == null) {
                String message = "Expires Text is null";
                throw new SavanException(message);
            }

            expiresText = expiresText.trim();

            ExpirationBean expirationBean = getExpirationBeanFromString(expiresText);
            Date expiration = null;
            if (expirationBean.isDuration()) {
                Calendar calendar = Calendar.getInstance();
                CommonUtil.addDurationToCalendar(calendar, expirationBean.getDurationValue());
                expiration = calendar.getTime();
            } else
                expiration = expirationBean.getDateValue();

            if (expiration == null) {
                String message = "Cannot understand the given date-time value for the Expiration";
                throw new SavanException(message);
            }

            eventingSubscriber.setSubscriptionEndingTime(expiration);
        } else {
            // They didn't specify an expiration, so default to an hour.
            Calendar calendar = Calendar.getInstance();
            Duration duration = new Duration();
            duration.setHours(1);
            CommonUtil.addDurationToCalendar(calendar, duration);
            eventingSubscriber.setSubscriptionEndingTime(calendar.getTime());
        }

        OMElement filterElement = subscribeElement.getFirstChildWithName(new QName(
                EventingConstants.EVENTING_NAMESPACE, EventingConstants.ElementNames.Filter));
        if (filterElement != null) {
            OMNode filterNode = filterElement.getFirstOMChild();
            OMAttribute dialectAttr =
                    filterElement.getAttribute(new QName(EventingConstants.ElementNames.Dialect));
            Filter filter = null;

            String filterKey = EventingConstants.DEFAULT_FILTER_IDENTIFIER;
            if (dialectAttr != null) {
                filterKey = dialectAttr.getAttributeValue();
            }
            filter = configurationManager.getFilterInstanceFromId(filterKey);
            if (filter == null)
                throw new SavanException("The Filter defined by the dialect is not available");

            filter.setUp(filterNode);

            eventingSubscriber.setFilter(filter);
        }

        return eventingSubscriber;
    }

    public void pauseSubscription(SavanMessageContext pauseSubscriptionMessage)
            throws SavanException {
        throw new UnsupportedOperationException(
                "Eventing specification does not support this type of messages");
    }

    public void resumeSubscription(SavanMessageContext resumeSubscriptionMessage)
            throws SavanException {
        throw new UnsupportedOperationException(
                "Eventing specification does not support this type of messages");
    }

    public ExpirationBean getExpirationBean(SavanMessageContext renewMessage)
            throws SavanException {

        SOAPEnvelope envelope = renewMessage.getEnvelope();
        SOAPBody body = envelope.getBody();

        ExpirationBean expirationBean = null;

        OMElement renewElement = body.getFirstChildWithName(new QName(
                EventingConstants.EVENTING_NAMESPACE, EventingConstants.ElementNames.Renew));
        if (renewElement == null) {
            String message = "Renew element not present in the assumed Renew Message";
            throw new SavanException(message);
        }

        OMElement expiresElement = renewElement.getFirstChildWithName(new QName(
                EventingConstants.EVENTING_NAMESPACE, EventingConstants.ElementNames.Expires));
        if (expiresElement != null) {
            String expiresText = expiresElement.getText().trim();
            expirationBean = getExpirationBeanFromString(expiresText);
        }

        String subscriberID = getSubscriberID(renewMessage);
        if (subscriberID == null) {
            String message = "Cannot find the subscriber ID";
            throw new SavanException(message);
        }

        renewMessage
                .setProperty(EventingConstants.TransferedProperties.SUBSCRIBER_UUID, subscriberID);

        expirationBean.setSubscriberID(subscriberID);
        return expirationBean;
    }

    public String getSubscriberID(SavanMessageContext smc) throws SavanException {
        SOAPEnvelope envelope = smc.getEnvelope();
        SOAPHeader header = envelope.getHeader();
        if (header == null) {
            return null;
        }

        OMElement ideltifierElement = envelope.getHeader().getFirstChildWithName(new QName(
                EventingConstants.EVENTING_NAMESPACE, EventingConstants.ElementNames.Identifier));
        if (ideltifierElement == null) {
            return null;
        }

        return ideltifierElement.getText().trim();
    }

    private ExpirationBean getExpirationBeanFromString(String expiresStr) throws SavanException {

        ExpirationBean bean = new ExpirationBean();

        //expires can be a duration or a date time.
        //Doing the conversion using the ConverUtil helper class.

        Date date = null;
        boolean isDuration = CommonUtil.isDuration(expiresStr);

        if (isDuration) {
            try {
                bean.setDuration(true);
                Duration duration = ConverterUtil.convertToDuration(expiresStr);
                bean.setDurationValue(duration);
            } catch (IllegalArgumentException e) {
                String message = "Cannot convert the Expiration value to a valid duration";
                throw new SavanException(message, e);
            }
        } else {
            try {
                Calendar calendar = ConverterUtil.convertToDateTime(expiresStr);
                date = calendar.getTime();
                bean.setDateValue(date);
            } catch (Exception e) {
                String message = "Cannot convert the Expiration value to a valid DATE/TIME";
                throw new SavanException(message, e);
            }
        }

        boolean invalidExpirationTime = false;
        if (bean.isDuration()) {
            if (isInvalidDiration(bean.getDurationValue()))
                invalidExpirationTime = true;
        } else {
            if (isDateInThePast(bean.getDateValue()))
                invalidExpirationTime = true;
        }

        if (invalidExpirationTime) {
            //TODO throw Invalid Expiration Time fault
        }

        return bean;
    }

    private boolean deliveryModesupported() {
        return true;
    }

    private boolean isInvalidDiration(Duration duration) {
        return false;
    }

    private boolean isDateInThePast(Date date) {
        return false;
    }

    private boolean filterDilalectSupported(String filterDialect) {
        return true;
    }

}
