//------------------------------------------------------------------------------
// <copyright file="Utility.java" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <summary>
//      Utility Functions
// </summary>
//------------------------------------------------------------------------------

package com.microsoft.hpc.scheduler.session;

import java.net.URI;
import java.util.Locale;

import javax.xml.soap.*;
import javax.xml.ws.soap.SOAPFaultException;


import com.microsoft.hpc.exceptions.*;
import com.microsoft.hpc.scheduler.session.internal.Constant;
import com.microsoft.hpc.session.*;


/**
 * Utility Functions
 */
public class Utility
{
    
    static boolean isEOM(SOAPMessage message)
    {
        return Constant.EndRequestsAction.equalsIgnoreCase(getAction(message));
        //Note: Currently, action in SOAPHeader == null;
    }
    
    /**
     * Logs error
     * @param message Error Message
     * @param args Arguments into error message
     */
    static void logError(String message, Object... args)
    {
    }
    
    /**
     * Throws Exception if arg is null
     * @param arg arg to check
     * @param name name of argument
     */
    public static void throwIfNull(Object arg, String name)
    {
        if (arg == null)
        {
            throw new ArgumentNullException(name);
        }
    }
    
    /**
     * Throws exception if arg is null or empty
     * @param arg arg to check
     * @param name name of argument
     */
    public static void throwIfNullOrEmpty(String arg, String name)
    {
        if (arg == null || arg == "")
        {
            throw new ArgumentNullException(name);
        }
    }
    
    /**
     * Throws Exception if specified len is too large
     * @param len length to check 
     * @param name name of argument 
     * @param maxLen maximum length
     * @param message error message
     * @param args error message arguments
     */
    public static void throwIfTooLong(int len, String name, int maxLen, String message, Object... args)
    {
        if( len > maxLen )
        {
            throw new ArgumentException(String.format(message, args), name);
        }
    }
    
    /**
     * if valid is not true, throws an exception
     * @param valid statement to verify
     * @param name argument name
     */
    public static void throwIfInvalid(Boolean valid, String name)
    {
        if(!valid)
        {
            throw new ArgumentException("Invalid argument", name);
        }
    }
    
    //internal static void SafeCloseCommunicateObject(SOATraceSource traceSource, I...)
    //  no communicate objects to close
    
    /**
     * Takes a SessionFault and translates to SessionException
     * @param fault retrieved by an exception with a getFault() method
     * @return SessionException
     */
    static SessionException translateFaultException(SessionFault fault)
    {
        SessionException sessionException = null;
        if(fault != null)
        {
            String errorMessage = fault.getReason().getValue();
            switch(SOAFaultCode.getEnum(fault.getCode()))
            {
                case Broker_AuthenticationFailure:
                    errorMessage = SR.AuthenticationFailed;
                    break;
                case NoAvailableBrokerNodes:
                    errorMessage = SR.NoBrokerNodeFound;
                    break;
                case StorageSpaceNotSufficient:
                    errorMessage = SR.StorageSpaceNotSufficient;
                    break;
                default:
                    String message = "Error code: " + fault.getCode();
                    if (message != null)
                    {
                        if (fault.getContext() == null || fault.getContext().getValue().getAnyType() == null)
                        {
                            errorMessage = message;
                        }
                        else
                        {
                            Object[] objArr = fault.getContext().getValue().getAnyType().toArray();
                            errorMessage = String.format(Locale.getDefault(), message, objArr);
                        }
                    }
                    break;
            }
            
            sessionException = new SessionException(fault.getCode(), errorMessage);
        }
        return sessionException;
    }
    
    /**
     * Takes a SessionFault and translates to SessionException
     * @param fault retrieved by an exception with a getFault() method
     * @param errorMessage detail message
     * @return SessionException
     */
    static SessionException translateFaultException(SessionFault fault, String errorMessage)
    {
        SessionException sessionException = null;
        if (fault != null)
        {
            sessionException = new SessionException(fault.getCode(), errorMessage);
        }
        return sessionException;
    }
    
    /**
     * Gets sessionlauncher epr from SessionStartInfo
     * @param info
     * @return SessionLauncher EPR as URI
     */
    public static URI getSessionLauncher(SessionStartInfo info)
    {
        try
        {
            if (info.transportScheme().get(0) == TransportScheme.Local.getName())
            {
                return new URI("net.pipe://localhost/SessionLauncher");
            }
            else
            {
                return new URI(String.format("net.tcp://%s:%s/SessionLauncher", info.headnode(), Constant.SessionLauncherPort));
            }
        }
        catch(Exception e)
        {
            return null;
        }
    }
    
    public static URI getSessionLauncher(String headnode)
    {
        try
        {
            //if (LocalSession.LocalBroker)
            //{
            //    return new URI("net.pipe://localhost/SessionLauncher");
            //}
            //else
            //{
            return new URI(String.format("net.tcp://%s:%s/SessionLauncher", headnode, Constant.SessionLauncherPort));
            //}
        }
        catch(Exception e)
        {
            return null;
        }
    }
    
    //Java Only
    /**
     * Get action from the header of the SOAPMessage in messageBuffer
     */
    static String getAction(SOAPMessage message)
    {
        String action = "";
        SOAPHeader soapHeader = null;
        try
        {
            soapHeader = message.getSOAPHeader();
        }
        catch(Exception e)
        {
            return "";
        }
            
        
        while(soapHeader.getChildElements().hasNext())
        {
            Node node = (Node) soapHeader.getChildElements().next();
            if(node.getNodeName().equalsIgnoreCase("Action"))
            {
                action = node.getNodeValue();
                break;
            }
            soapHeader.getChildElements().remove();
        }
        return action;
    }
    
    static SOAPVersion getSOAPVersion(SOAPMessage message) throws SOAPFaultException, SOAPException
    {
        String contentType = message.getMimeHeaders().getHeader("Content-Type")[0];
         
        if(contentType == SOAPConstants.SOAP_1_1_CONTENT_TYPE)
        {
            return SOAPVersion.valueOf("SOAP11");
        }
        else if(contentType == SOAPConstants.SOAP_1_2_CONTENT_TYPE)
        {
            return SOAPVersion.valueOf("SOAP12");
        }
        else
           throw new SOAPFaultException(SOAPFactory.newInstance().createFault("Invalid SOAP version", SOAPConstants.SOAP_VERSIONMISMATCH_FAULT));
    }
       
}
