/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.ode.bpel.epr;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.Namespaces;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.namespace.QName;
import java.util.HashMap;
import java.util.Map;

/**
 * A service endpoint represented as a WS-Addressing EndpointReference.
 */
public class WSAEndpoint implements MutableEndpoint {

    private static final Logger __log = LoggerFactory.getLogger(WSAEndpoint.class);

    private Element _eprElmt;

    public WSAEndpoint() {
    }

    // prototype constructor
    public WSAEndpoint(WSAEndpoint prototype) {
        _eprElmt = (Element)DOMUtils.newDocument().importNode(prototype._eprElmt, true);
    }

    public WSAEndpoint(Map map) {
        this();
        fromMap(map);
    }

    public String getSessionId() {
        NodeList idNodes = _eprElmt.getElementsByTagNameNS(Namespaces.ODE_SESSION_NS, "session");
        if (idNodes.getLength() > 0) {
            return idNodes.item(0).getTextContent();
        } else {
            // try the same with the intalio header
            idNodes = _eprElmt.getElementsByTagNameNS(Namespaces.INTALIO_SESSION_NS, "session");
            if (idNodes.getLength() > 0) {
                return idNodes.item(0).getTextContent();
            }
            return null;
        }
    }

    public void setSessionId(String sessionId) {
        NodeList idList = _eprElmt.getElementsByTagNameNS(Namespaces.ODE_SESSION_NS, "session");
        if (idList.getLength() > 0)
            idList.item(0).setTextContent(sessionId);
        else {
            Element sessElmt = _eprElmt.getOwnerDocument().createElementNS(Namespaces.ODE_SESSION_NS, "session");
            sessElmt.setTextContent(sessionId);
            _eprElmt.appendChild(sessElmt);
        }

        // and the same for the intalio header
        idList = _eprElmt.getElementsByTagNameNS(Namespaces.INTALIO_SESSION_NS, "session");
        if (idList.getLength() > 0)
            idList.item(0).setTextContent(sessionId);
        else {
            Element sessElmt = _eprElmt.getOwnerDocument().createElementNS(Namespaces.INTALIO_SESSION_NS, "session");
            sessElmt.setTextContent(sessionId);
            _eprElmt.appendChild(sessElmt);
        }
    }

    public String getUrl() {
        return _eprElmt.getElementsByTagNameNS(Namespaces.WS_ADDRESSING_NS, "Address").item(0).getTextContent().trim();
    }

    public void setUrl(String url) {
        NodeList addrList = _eprElmt.getElementsByTagNameNS(Namespaces.WS_ADDRESSING_NS, "Address");
        if (addrList.getLength() > 0)
            addrList.item(0).setTextContent(url);
        else {
            Element addrElmt = _eprElmt.getOwnerDocument().createElementNS(Namespaces.WS_ADDRESSING_NS, "Address");
            addrElmt.setTextContent(url);
            _eprElmt.appendChild(addrElmt);
        }
    }

    public QName getServiceName() {
        NodeList metadataList = _eprElmt.getElementsByTagNameNS(Namespaces.WS_ADDRESSING_NS, "Metadata");
        if (metadataList.getLength() > 0) {
            Element metadata = (Element) metadataList.item(0);
            Element service = DOMUtils.getFirstChildElement(metadata);
            String serviceTextQName = service.getTextContent();
            int twoDotsIdx = serviceTextQName.indexOf(":");
            String prefix = serviceTextQName.substring(0, twoDotsIdx);
            String serviceNS = _eprElmt.getOwnerDocument().lookupNamespaceURI(prefix);
            // Lookup failed, checking directly on our element
            if (serviceNS == null) {
                serviceNS = service.getAttribute("xmlns:" + prefix);
            }
            if (serviceNS == null)
                __log.warn("Couldn't find an appropriate namespace for service!");
            QName result = new QName(serviceNS, serviceTextQName.substring(twoDotsIdx + 1, serviceTextQName.length()));
            if (__log.isDebugEnabled())
                __log.debug("Got service name from WSAEndpoint: " + result);
            return result;
        }
        return null;
    }

    public String getPortName() {
        NodeList metadataList = _eprElmt.getElementsByTagNameNS(Namespaces.WS_ADDRESSING_NS, "Metadata");
        if (metadataList.getLength() > 0) {
            Element metadata = (Element) metadataList.item(0);
            Element service = DOMUtils.getFirstChildElement(metadata);
            return service.getAttribute("EndpointName");
        }
        return null;
    }

    public boolean accept(Node node) {
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            Element elmt = (Element) node;
            if (elmt.getLocalName().equals(SERVICE_REF_QNAME.getLocalPart())
                    && elmt.getNamespaceURI().equals(SERVICE_REF_QNAME.getNamespaceURI()))
                elmt = DOMUtils.getFirstChildElement(elmt);
            if (elmt != null && elmt.getLocalName().equals("EndpointReference")
                    && elmt.getNamespaceURI().equals(Namespaces.WS_ADDRESSING_NS))
                return true;
        }
        return false;
    }

    public void set(Node node) {
        if (node.getNamespaceURI().equals(SERVICE_REF_QNAME.getNamespaceURI()))
            _eprElmt = DOMUtils.getFirstChildElement((Element) node);
        else
            _eprElmt = (Element) node;
        if (__log.isDebugEnabled())
            __log.debug("Setting a WSAEndpoint value: " + DOMUtils.domToString(_eprElmt));
    }

    public Document toXML() {
        // Wrapping
        Document doc = DOMUtils.newDocument();
        Element serviceRef = doc.createElementNS(SERVICE_REF_QNAME.getNamespaceURI(), SERVICE_REF_QNAME.getLocalPart());
        doc.appendChild(serviceRef);
        serviceRef.appendChild(doc.importNode(_eprElmt, true));
        return doc;
    }

    public Map toMap() {
        HashMap<String, Object> result = new HashMap<String, Object>();
        result.put(ADDRESS, getUrl());
        String sid = getSessionId();
        if (sid != null)
            result.put(SESSION, sid);
        NodeList metadataList = _eprElmt.getElementsByTagNameNS(Namespaces.WS_ADDRESSING_NS, "Metadata");
        if (metadataList.getLength() > 0) {
            Element metadata = (Element) metadataList.item(0);
            Element service = DOMUtils.getFirstChildElement(metadata);
            String serviceTextQName = service.getTextContent();
            int twoDotsIdx = serviceTextQName.indexOf(":");
            String prefix = serviceTextQName.substring(0, twoDotsIdx);
            String serviceNS = null;
            try {
                serviceNS = _eprElmt.getOwnerDocument().lookupNamespaceURI(prefix);
            } catch (Exception e) {
                __log.error(e.getMessage(), e);
            }
            // Lookup failed, checking directly on our element
            if (serviceNS == null) {
                serviceNS = service.getAttribute("xmlns:" + prefix);
            }
            result.put(SERVICE_QNAME, new QName(serviceNS, serviceTextQName.substring(twoDotsIdx + 1, serviceTextQName
                    .length())));
            result.put(PORT_NAME, service.getAttribute("EndpointName"));
            if (__log.isDebugEnabled()) {
                __log.debug("Filled transfo map with service: " + result.get(SERVICE_QNAME));
                __log.debug("Filled transfo map with port: " + result.get(PORT_NAME));
            }
        }
        return result;
    }

    public void fromMap(Map eprMap) {
        Document doc = DOMUtils.newDocument();
        Element serviceRef = doc.createElementNS(SERVICE_REF_QNAME.getNamespaceURI(), SERVICE_REF_QNAME.getLocalPart());
        doc.appendChild(serviceRef);
        _eprElmt = doc.createElementNS(Namespaces.WS_ADDRESSING_NS, "EndpointReference");
        serviceRef.appendChild(_eprElmt);
        Element addrElmt = doc.createElementNS(Namespaces.WS_ADDRESSING_NS, "Address");
        addrElmt.setTextContent((String) eprMap.get(ADDRESS));
        if (eprMap.get(SESSION) != null) {
            Element sessElmt = doc.createElementNS(Namespaces.ODE_SESSION_NS, "session");
            sessElmt.setTextContent((String) eprMap.get(SESSION));
            _eprElmt.appendChild(sessElmt);
            // and the same for the (deprecated) intalio namespace for backward compatibility
            sessElmt = doc.createElementNS(Namespaces.INTALIO_SESSION_NS, "session");
            sessElmt.setTextContent((String) eprMap.get(SESSION));
            _eprElmt.appendChild(sessElmt);
        }
        if (eprMap.get(SERVICE_QNAME) != null) {
            Element metadataElmt = doc.createElementNS(Namespaces.WS_ADDRESSING_NS, "Metadata");
            _eprElmt.appendChild(metadataElmt);
            Element serviceElmt = doc.createElementNS(Namespaces.WS_ADDRESSING_WSDL_NS, "ServiceName");
            metadataElmt.appendChild(serviceElmt);
            QName serviceQName = (QName) eprMap.get(SERVICE_QNAME);
            serviceElmt.setAttribute("xmlns:servicens", serviceQName.getNamespaceURI());
            serviceElmt.setTextContent("servicens:" + serviceQName.getLocalPart());
            serviceElmt.setAttribute("EndpointName", (String) eprMap.get(PORT_NAME));
        }
        _eprElmt.appendChild(addrElmt);
        if (__log.isDebugEnabled())
            __log.debug("Constructed a new WSAEndpoint: " + DOMUtils.domToString(_eprElmt));
    }
}
