// StearnsEngineering.com
// Kelly Stearns

package com.cisco.ipphone.sdk.wfapi;

//import com.cisco.ipphone.sdk.*;

import com.cisco.wfapi.*;
import com.cisco.wfapi.step.*;
import com.cisco.wfapi.step.jbstep.WFJBStep;
import com.cisco.wfapi.expression.*;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
//import java.beans.*;
import java.beans.Introspector;
import java.beans.IntrospectionException;
import java.beans.BeanDescriptor;

import java.util.*;
import java.io.*;
//import javax.mail.*;
//import javax.mail.internet.*;
//import javax.activation.*;

import com.cisco.services.alarm.ParameterList;


public class StepPhonePush extends WFJBStep
{
	// for serialization, generated by serialver tools comes with JDK
    private static final long serialVersionUID = 4231163436238681556L;

	static final String STEP_NAME = "PhonePush";
	static final String SUBFACILITYNAME = "IP_PHONE_STEPS";

	// labels for output points
	static final String STEP_CONNECTION_0 = "Success";
	static final String STEP_CONNECTION_1 = "Fail";

	// output points indecies
	static final int STEP_CONNECTION_SUCCESS = 0;
	static final int STEP_CONNECTION_FAIL = 1;

        static final int TYPE_DEVICENAME = 0;
        static final int TYPE_EXTENSION = 1;

	private String strTypeName = null;
	private transient WFTracingLog tLog = null;

	// fields for email header as expressions
	// specified by user (from customizer)
	private String xmlDataExpr = "";
	private String targetExpr= "";

        private transient String target = null;
	private transient String xmlData = null;
        private transient int targetType = TYPE_DEVICENAME;

	public StepPhonePush()
	{
		// set the number of output points and their labels.
	    setNumberOfOutputPoints(2);
	    setOutputLabelAt(0, STEP_CONNECTION_0);
	    setOutputLabelAt(1, STEP_CONNECTION_1);
	}

	//////////////////////////////////////////////////////////
	// the following members implement the WFStep interface

	public void compile(CompilationReport report)
	{
        WFContextDefinition context = getContainer().getContextDefinition();
   		Expression expr = new Expression();

	    try {
			// required entries
			if (!expr.validate(context, targetExpr, java.lang.String.class, false))
				report.addCompileError(getDescription() + ": Invalid phone name " + targetExpr, CompilationReport.ERROR_LEVEL1);
			if (!expr.validate(context, xmlDataExpr, java.lang.String.class, false))
				report.addCompileError(getDescription() + ": Invalid XML Data " + xmlDataExpr, CompilationReport.ERROR_LEVEL1);

			// Optional fields

		} catch (WFExpressionException e) {
			report.addCompileError(getDescription() + ": " + e.getMessage(), CompilationReport.ERROR_LEVEL1);
		} catch (Exception e) {
			report.addCompileError(getDescription() + ": " + e.getMessage(), CompilationReport.ERROR_LEVEL1);
		}

		return;
	}

	public void preprocess() throws WFPreprocessException
	{
		registerTracingService(SUBFACILITYNAME);
	    return;
	}

	// main logic of the step
	public int execute(WFWorkflowTask task)
	    throws WFExecutionException
	{
		WFContext context = task.getContext();

		try {

		Expression expr = new Expression();
		expr.validate(context, targetExpr, String.class, false);
                target = (String)(expr.evaluate(context));

		expr.validate(context, xmlDataExpr, String.class, false);
		xmlData = (String)(expr.evaluate(context));


		// Optional fields

		} catch(Exception e) {
			// trace and log
			tLog.trace("Exception occurred in processing properties of Phone PUSH Step", e);
			ParameterList paramList = tLog.createNewParameterList ();
			paramList.addParameter("SCRIPT_NAME", getContainer().getName());
			paramList.addParameter("ERROR_MESSAGE", e.getMessage());
			tLog.sendAlarm("PHONE_PUSH_FAIL", paramList);
			return STEP_CONNECTION_FAIL;
    	      }

              boolean result;
              if (targetType == TYPE_DEVICENAME) {
                tLog.trace("Executing pushToPhone()");
                result = IPPhoneServicesSubsystem.instance.pushToPhone(target, xmlData);
              }
              else {
                tLog.trace("Executing pushToExtension()");
                result = IPPhoneServicesSubsystem.instance.pushToExtension(target, xmlData);
              }
              return (result) ? STEP_CONNECTION_SUCCESS : STEP_CONNECTION_FAIL;
	}

	/**
	 * Gets the type for the step from the associated BeanInfo object
	 */
	public String getTypeName()
	{
		// Lazy initialization
		if (strTypeName == null)
		{
			strTypeName = "null";
			try
			{
				BeanDescriptor bd = Introspector.getBeanInfo(getClass()).getBeanDescriptor();
				if (bd != null)
				{
					strTypeName = bd.getDisplayName();
				}
			}
			catch (IntrospectionException e)
			{
			}
			catch (Exception e)
			{
			}
		}

		return strTypeName;
	}

	/**
	 * Returns the description of the current step
	 */
	public String getDescription()
	{
	    return "PhonePush to " + targetExpr;
	}

	public String getCompanyName()
	{
		return "Cisco Systems, Inc.";
	}

	public int getMajorVersion()
	{
		return 1;
	}

	public int getMinorVersion()
	{
		return 0;
	}

	// The following methods are implemented for supporting versioning
	private void readObject(java.io.ObjectInputStream in)
		throws java.io.IOException, java.lang.ClassNotFoundException
	{
		long objectVersion = in.readLong();

		if(objectVersion == getVersionID())
		{
			readObjectCurrentVersion(in);
		}
		else
		{
			readObjectIncompatibleVersion(objectVersion, in);
		}
	}

	private void writeObject(java.io.ObjectOutputStream out)
		throws java.io.IOException
	{
		out.writeLong(getVersionID());

		writeObjectCurrentVersion(out);
	}

	private final static long CURRENT_VERSION = 1;

	private long getVersionID()
	{
		return CURRENT_VERSION;
	}

	private void readObjectCurrentVersion(ObjectInputStream stream)
		throws java.io.IOException, java.lang.ClassNotFoundException
	{
		targetExpr = (String) stream.readObject();
		xmlDataExpr = (String) stream.readObject();
                targetType = stream.readInt();
	}

	private void writeObjectCurrentVersion(ObjectOutputStream stream)
		throws java.io.IOException
	{
		stream.writeObject(targetExpr);
		stream.writeObject(xmlDataExpr);
                stream.writeInt(targetType);
	}

	private void readObjectIncompatibleVersion(long versionID, ObjectInputStream stream)
		throws java.io.IOException, java.lang.ClassNotFoundException
	{
	}

	///////////////////////////////////////////////////////////
	// The following members are helpers to implement the WFStep
	// interface

	// get runtime container
	private WFWorkflowRTContainer getWorkflowRTContainer()
	{
		WFWorkflow myContainer = getContainer();
		WFWorkflowContainer wfc = myContainer.getContainer();
		if(wfc != null && wfc instanceof WFWorkflowRTContainer)
		{
			return (WFWorkflowRTContainer) wfc;
		}
		return null;
	}

	// Register with the tracing service
	protected void registerTracingService(String facility)
	{
		WFWorkflowRTContainer rtc = getWorkflowRTContainer();
		tLog = rtc.addTracingService(facility);
	}

	/////////////////////////////////////////////////////////////
	// The following members are specific to this step

	// accessors for step properties
	public String getXmlData()
	{
		 return xmlDataExpr;
	}

	public void setXmlData(String xmlData)
	{
		 xmlDataExpr = xmlData;
	}

	public String getTarget()
	{
		 return targetExpr;
	}

	public void setTarget(String t)
	{
		 targetExpr = t;
	}

        public int getTargetType() {
          return targetType;
        }

        public void setTargetType(int type) {
          targetType = type;
        }


}