/*
 * Copyright  2003-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.ws.security.message.token;

import java.util.Enumeration;
import java.util.Hashtable;

import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.conversation.ConversationConstants;
import org.apache.ws.security.conversation.ConversationException;
import org.apache.ws.security.util.DOM2Writer;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

/**
 <DerivedKeyToken wsu:Id="..." wsc:Algorithm="...">
 <SecurityTokenReference>...</SecurityTokenReference>
 <Properties>...</Properties>
 <Generation>...</Generation>
 <Offset>...</Offset>
 <Length>...</Length>
 <Label>...</Label>
 <Nonce>...</Nonce>
 </DerivedKeyToken>
 */

/**
 * @author Ruchith Fernando
 * @version 1.0
 */
public class DerivedKeyToken {

    private Log log = LogFactory.getLog(DerivedKeyToken.class.getName());


    //These are the elements that are used to create the SecurityContextToken
    protected Element element = null;
    protected Element elementSecurityTokenReference = null;
    protected Element elementProperties = null;
    protected Element elementGeneration = null;
    protected Element elementOffset = null;
    protected Element elementLength = null;
    protected Element elementLabel = null;
    protected Element elementNonce = null;
    
    private String ns;
    
    /**
     * This will create an empty DerivedKeyToken
     *
     * @param doc THe DOM document
     */
    public DerivedKeyToken(Document doc) throws ConversationException {
        this(ConversationConstants.DEFAULT_VERSION, doc);
    }

    /**
     * This will create an empty DerivedKeyToken
     *
     * @param doc THe DOM document
     */
    public DerivedKeyToken(int version, Document doc) throws ConversationException {
        
        log.debug("DerivedKeyToken: created");
        
        this.ns = ConversationConstants.getWSCNs(version);
        
        this.element = doc.createElementNS(ns,
                "wsc:" +
                ConversationConstants.
                DERIVED_KEY_TOKEN_LN);
        WSSecurityUtil.setNamespace(this.element, ns,
                ConversationConstants.WSC_PREFIX);
    }

    /**
     * This will create a DerivedKeyToken object with the given DErivedKeyToken element
     *
     * @param elem The DErivedKeyToken DOM element
     * @throws WSSecurityException If the element is not a derived key token
     */
    public DerivedKeyToken(Element elem) throws WSSecurityException {
        log.debug("DerivedKeyToken: created : element constructor");
        this.element = elem;
        QName el = new QName(this.element.getNamespaceURI(),
                this.element.getLocalName());
        if (!el.equals(new QName(ConversationConstants.WSC_NS_05_02, ConversationConstants.DERIVED_KEY_TOKEN_LN)) &&
                !el.equals(new QName(ConversationConstants.WSC_NS_05_12, ConversationConstants.DERIVED_KEY_TOKEN_LN))) {
            throw new WSSecurityException(WSSecurityException.INVALID_SECURITY_TOKEN,
                    "badTokenType00", new Object[]{el});
        }
        this.elementSecurityTokenReference = (Element) WSSecurityUtil.
                getDirectChild(this.element,
                        ConversationConstants.SECURITY_TOKEN_REFERENCE_LN,
                        WSConstants.WSSE_NS);
        
        this.ns = el.getNamespaceURI();
        
        this.elementProperties = (Element) WSSecurityUtil.getDirectChild(this.
                element, ConversationConstants.PROPERTIES_LN, this.ns);
        this.elementGeneration = (Element) WSSecurityUtil.getDirectChild(this.
                element, ConversationConstants.GENERATION_LN, this.ns);
        this.elementOffset = (Element) WSSecurityUtil.getDirectChild(this.element,
                ConversationConstants.OFFSET_LN, this.ns);
        this.elementLength = (Element) WSSecurityUtil.getDirectChild(this.element,
                ConversationConstants.LENGTH_LN, this.ns);
        this.elementLabel = (Element) WSSecurityUtil.getDirectChild(this.element,
                ConversationConstants.LABEL_LN, this.ns);
        this.elementNonce = (Element) WSSecurityUtil.getDirectChild(this.element,
                ConversationConstants.NONCE_LN, this.ns);
    }

    /**
     * Sets the security token reference of the derived key token
     * This is the reference to the shared secret used in the conversation/context
     *
     * @param ref Security token reference
     */
    public void setSecurityTokenReference(SecurityTokenReference ref) {
        this.elementSecurityTokenReference = ref.getElement();
        //WSSecurityUtil.appendChildElement(doc, this.element, ref.getElement());
        WSSecurityUtil.prependChildElement(this.element.getOwnerDocument(), this.element, ref.getElement(), false);
    }
    
    /**
     * Sets the security token reference of the derived key token
     * This is the reference to the shared secret used in the conversation/context
     *
     * @param ref Security token reference
     * @deprecated use setSecurityTokenReference(SecurityTokenReference ref) instead
     */
    public void setSecuityTokenReference(SecurityTokenReference ref) {
        setSecurityTokenReference(ref);
    }
    
    public void setSecurityTokenReference(Element elem) {
        this.elementSecurityTokenReference = elem;
        WSSecurityUtil.prependChildElement(elem.getOwnerDocument(), this.element, elem, false);
    }
    
    /**
     * @deprecated use setSecurityTokenReference(Element elem) instead
     */
    public void setSecuityTokenReference(Element elem) {
        setSecurityTokenReference(elem);
    }

    /**
     * Returns the SecurityTokenReference of the derived key token
     *
     * @return the Security Token Reference of the derived key token
     * @throws WSSecurityException
     */
    public SecurityTokenReference getSecurityTokenReference() throws
            WSSecurityException {
        if (this.elementSecurityTokenReference != null) {
            return new SecurityTokenReference(this.elementSecurityTokenReference);
        }
        return null;
    }
    
    /**
     * Returns the SecurityTokenReference of the derived key token
     *
     * @return the Security Token Reference of the derived key token
     * @throws WSSecurityException
     * @deprecated use getSecurityTokenReference() instead
     */
    public SecurityTokenReference getSecuityTokenReference() throws
            WSSecurityException {
        return getSecurityTokenReference();
    }

    //Write the getter for security token reference

    /**
     * This adds a property into
     * /DerivedKeyToken/Properties
     *
     * @param propName  Name of the property
     * @param propValue Value of the property
     */
    private void addProperty(String propName, String propValue) {
        if (this.elementProperties == null) { //Create the properties element if it is not there
            this.elementProperties = this.element.getOwnerDocument().createElementNS(this.ns,
                    "wsc:" +
                    ConversationConstants.PROPERTIES_LN);
            WSSecurityUtil.setNamespace(this.elementProperties,
                    this.ns,
                    WSConstants.WSSE_PREFIX);
            this.element.appendChild(this.elementProperties);
        }
        Element tempElement = this.element.getOwnerDocument().createElementNS(this.ns,
                "wsc:" + propName);
        tempElement.appendChild(this.element.getOwnerDocument().createTextNode(propValue));

        this.elementProperties.appendChild(tempElement);
    }

    /**
     * This is used to set the Name, Label and Nonce element values in the properties element
     * <b>At this point I'm not sure if these are the only properties that will appear in the
     * <code>Properties</code> element. There fore this method is provided
     * If this is not required feel free to remove this :D
     * </b>
     *
     * @param name  Value of the Properties/Name element
     * @param label Value of the Properties/Label element
     * @param nonce Value of the Properties/Nonce element
     */
    public void setProperties(String name, String label,
                              String nonce) {
        Hashtable table = new Hashtable(3);
        table.put("Name", name);
        table.put("Label", label);
        table.put("Nonce", nonce);
        this.setProperties(table);
    }

    /**
     * If there are other types of properties other than Name, Label and Nonce
     * This is provided for extensibility purposes
     *
     * @param properties The properties and values in a hashtable
     */
    public void setProperties(Hashtable properties) {
        Enumeration keys = properties.keys();
        while (keys.hasMoreElements()) {
            String propertyName = (String) keys.nextElement(); //Get the property name
            //Check whether this property is already there
            //If so change the value
            Node node = WSSecurityUtil.findElement(this.elementProperties,
                    propertyName,
                    this.ns);
            if (node != null && node instanceof Element) { //If the node is not null
                Text node1 = getFirstNode((Element) node);
                node1.setData((String) properties.get(propertyName));
            } else {
                this.addProperty(propertyName,
                        (String) properties.get(propertyName));
            }
        }
    }

    public Hashtable getProperties() {
        if (this.elementProperties != null) {
            Hashtable table = new Hashtable();
            NodeList nodes = this.elementProperties.getChildNodes();
            for (int i = 0; i < nodes.getLength(); i++) {
                Node tempNode = nodes.item(i);
                if (tempNode instanceof Element) {
                    Text text = this.getFirstNode((Element) tempNode);
                    table.put(tempNode.getNodeName(), text.getData());
                }
            }

        }
        return null;
    }

    /**
     * Sets the length of the derived key
     *
     * @param length The length of the derived key as a long
     */
    public void setLength(int length) {
        this.elementLength = this.element.getOwnerDocument().createElementNS(this.ns,
                "wsc:" +
                ConversationConstants.LENGTH_LN);
        WSSecurityUtil.setNamespace(this.elementLength,
                this.ns,
                ConversationConstants.WSC_PREFIX);
        this.elementLength.appendChild(this.element.getOwnerDocument().createTextNode(Long.toString(length)));
        this.element.appendChild(this.elementLength);
    }

    public int getLength() {
        if (this.elementLength != null) {
            return Integer.parseInt(getFirstNode(this.elementLength).getData());
        }
        return -1;
    }

    /**
     * Sets the offset
     *
     * @param offset The offset value as an integer
     */
    public void setOffset(int offset) throws ConversationException {
        //This element MUST NOT be used if the <Generation> element is specified
        if (this.elementGeneration == null) {
            this.elementOffset = this.element.getOwnerDocument().createElementNS(this.ns,
                    "wsc:" +
                    ConversationConstants.OFFSET_LN);
            WSSecurityUtil.setNamespace(this.elementOffset,
                    this.ns,
                    ConversationConstants.WSC_PREFIX);
            this.elementOffset.appendChild(this.element.getOwnerDocument().createTextNode(Integer.toString(offset)));
            this.element.appendChild(this.elementOffset);
        } else {
            throw new ConversationException("Offset cannot be set along with generation - generation is already set");
        }

    }

    public int getOffset() {
        if (this.elementOffset != null) {
            return Integer.parseInt(getFirstNode(this.elementOffset).getData());
        }
        return -1;
    }

    /**
     * Sets the generation of the derived key
     *
     * @param generation generation value as an integer
     */
    public void setGeneration(int generation) throws
            ConversationException {
        //This element MUST NOT be used if the <Offset> element is specified
        if (this.elementOffset == null) {
            this.elementGeneration = this.element.getOwnerDocument().createElementNS(this.ns,
                    "wsc:" + ConversationConstants.GENERATION_LN);
            WSSecurityUtil.setNamespace(this.elementGeneration,
                    this.ns,
                    ConversationConstants.WSC_PREFIX);
            this.elementGeneration.appendChild(this.element.getOwnerDocument().createTextNode(Integer.toString(generation)));
            this.element.appendChild(this.elementGeneration);
        } else {
            throw new ConversationException("Generation cannot be set along with offset - Offset is already set");
        }
    }

    public int getGeneration() {
        if (this.elementGeneration != null) {
            return Integer.parseInt(getFirstNode(this.elementGeneration).getData());
        }
        return -1;
    }

    /**
     * Sets the label of the derived key
     *
     * @param label Label value as a string
     */
    public void setLabel(String label) {
        this.elementLabel = this.element.getOwnerDocument().createElementNS(this.ns,
                "wsc:" +
                ConversationConstants.LABEL_LN);
        WSSecurityUtil.setNamespace(this.elementLabel, this.ns,
                ConversationConstants.WSC_PREFIX);
        this.elementLabel.appendChild(this.element.getOwnerDocument().createTextNode(label));
        this.element.appendChild(this.elementLabel);
    }

    /**
     * Sets the nonce value of the derived key
     *
     * @param nonce Nonce value as a string
     */
    public void setNonce(String nonce) {
        this.elementNonce = this.element.getOwnerDocument().createElementNS(this.ns,
                "wsc:" +
                ConversationConstants.NONCE_LN);
        WSSecurityUtil.setNamespace(this.elementNonce, this.ns,
                ConversationConstants.WSC_PREFIX);
        this.elementNonce.appendChild(this.element.getOwnerDocument().createTextNode(nonce));
        this.element.appendChild(this.elementNonce);

    }

    /**
     * Returns the label of the derived key token
     *
     * @return Label of the derived key token
     */
    public String getLabel() {
        if (this.elementLabel != null) {
            return getFirstNode(this.elementLabel).getData();
        }
        return null;
    }

    /**
     * Return the nonce of the derived key token
     *
     * @return Nonce of the derived key token
     */
    public String getNonce() {
        if (this.elementNonce != null) {
            return getFirstNode(this.elementNonce).getData();
        }
        return null;
    }

    /**
     * Returns the first text node of an element.
     *
     * @param e the element to get the node from
     * @return the first text node or <code>null</code> if node
     *         is null or is not a text node
     */
    private Text getFirstNode(Element e) {
        Node node = e.getFirstChild();
        return ((node != null) && node instanceof Text) ? (Text) node : null;
    }

    /**
     * Returns the dom element of this <code>SecurityContextToken</code> object.
     *
     * @return the DerivedKeyToken element
     */
    public Element getElement() {
        return this.element;
    }

    /**
     * Returns the string representation of the token.
     *
     * @return a XML string representation
     */
    public String toString() {
        return DOM2Writer.nodeToString((Node) this.element);
    }

    /**
     * Gets the id.
     *
     * @return the value of the <code>wsu:Id</code> attribute of this
     *         DerivedKeyToken
     */
    public String getID() {
        return this.element.getAttributeNS(WSConstants.WSU_NS, "Id");
    }

    /**
     * Set the id of this derived key token.
     *
     * @param id the value for the <code>wsu:Id</code> attribute of this
     *           DerivgedKeyToken
     */
    public void setID(String id) {
        String prefix = WSSecurityUtil.setNamespace(this.element,
                WSConstants.WSU_NS,
                WSConstants.WSU_PREFIX);
        this.element.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
    }

    /**
     * Gets the derivation algorithm
     *
     * @return the value of the <code>wsc:Algorithm</code> attribute of this
     *         DerivedKeyToken
     */
    public String getAlgorithm() {
        String algo = this.element.getAttributeNS(this.ns,
                "Algorithm");
        if (algo == null || algo.equals("")) {
            return ConversationConstants.DerivationAlgorithm.P_SHA_1;
        } else {
            return algo;
        }
    }

    /**
     * Set the derivation algorithm of this derived key token.
     *
     * @param algo the value for the <code>wsu:Algorithm</code> attribute of this
     *                    DerivedKeyToken
     */
    public void setAlgorithm(String algo) {
        String prefix = WSSecurityUtil.setNamespace(this.element,
                this.ns,
                ConversationConstants.
                WSC_PREFIX);
        this.element.setAttributeNS(this.ns,
                prefix + ":Algorithm", algo);
    }

}
