package upnp;

/**
 * Interface.java
 *
 *
 * Created: Mon Oct 25 19:45:53 2004
 *
 * @author <a href="mailto:newmarch@jannote.jan.home">Jan Newmarch</a>
 * @version 1.0
 *
 * Create new service interfaces from a UPnP description
 */

import org.cybergarage.upnp.Device;
import org.cybergarage.upnp.ServiceList;
import org.cybergarage.upnp.Service;
import org.cybergarage.upnp.ActionList;
import org.cybergarage.upnp.Action;
import org.cybergarage.upnp.ServiceStateTable;
import org.cybergarage.upnp.StateVariable;
import org.cybergarage.upnp.ArgumentList;
import org.cybergarage.upnp.Argument;
import org.cybergarage.xml.Node;
import org.cybergarage.xml.Parser;
import org.cybergarage.upnp.device.InvalidDescriptionException;
import org.cybergarage.upnp.UPnP;
import org.cybergarage.upnp.device.Description;
import org.cybergarage.xml.ParserException;
import org.cybergarage.upnp.xml.DeviceData;

// import org.cybergarage.upnp
import java.io.File;

public class Interface /*extends Device*/ {
    
    private Node deviceNode;
    private Node rootNode;
    private final static String URLBASE_NAME = "URLBase";
    
    public Interface() {
	
    }
    
    public static void main(String[] args) throws Exception {
	if (args.length != 1) {
	    System.err.println("Usage: java Interface deviceFile");
	    System.exit(1);
	}
	
	File deviceFile = new File(args[0]);
	new Interface(deviceFile);
    }
    
    public Interface(File deviceFile) throws Exception {
	//super(deviceFile);
	loadDescription(deviceFile);

	System.out.println("base url " + rootNode.getNodeValue("URLBase"));	

	ServiceList serviceList = getServiceList();
	int serviceCnt = serviceList.size();
	for (int n = 0; n < serviceCnt; n++) {
	    StringBuffer buf = new StringBuffer("package upnp.service;\n\n" +
						"import java.rmi.Remote;\n" +
						"import java.rmi.RemoteException;\n\n");
	    Service service = serviceList.getService(n);
	    Node serviceNode = service.getServiceNode();
	    System.out.println("Control URL: " + service.getControlURL());

	    String serviceType = service.getServiceType().
		replace(':', '_').
		replace('-', '_');
	    buf.append("public interface " + serviceType + " extends Remote {\n");
	    ActionList actionList = service.getActionList();
	    int actionCnt = actionList.size();
	    for (int i=0; i<actionCnt; i++) {
		Action action = actionList.getAction(i);
		System.out.println("action [" + i + "] = " + action.getName());
		buf.append("    void " + action.getName() + "(");
		
		ArgumentList argList = action.getInputArgumentList();
		System.out.println("  Input arg list");
	        for (int j = 0; j < argList.size(); j++) {
		    Argument arg = argList.getArgument(j);
		    System.out.println("    arg: " + arg.getName());
		    StateVariable stateVar = arg.getRelatedStateVariable();
		    System.out.println("      type: " + stateVar.getDataType());
		    buf.append(stateVar.getDataType() + " " + arg.getName()); 
		}
		
		argList = action.getOutputArgumentList();
		System.out.println("  Output arg list");
	        for (int j = 0; j < argList.size(); j++) {
		    Argument arg = argList.getArgument(j);
		    System.out.println("    arg: " + arg.getName());
		    StateVariable stateVar = arg.getRelatedStateVariable();
		    System.out.println("      type: " + stateVar.getDataType());
		    buf.append(stateVar.getDataType() + "Holder " + arg.getName()); 
		}
		buf.append(") throws RemoteException;\n");		
	    }
	    buf.append("}\n");
	    
	    ServiceStateTable stateTable = service. getServiceStateTable ();
	    int varCnt = stateTable.size();
	    for (int i=0; i<varCnt; i++) {
		StateVariable stateVar = stateTable.getStateVariable(i);
		System.out.println("stateVar [" + i + "] = " + stateVar.getName());
	    }
	    System.out.println("Interface:\n" + buf.toString());
	}
    }
    
    public ServiceList getServiceList() {
	ServiceList serviceList = new ServiceList();
	Node serviceListNode = deviceNode.getNode(ServiceList.ELEM_NAME);
	if (serviceListNode == null)
	    return serviceList;
	int nNode = serviceListNode.getNNodes();
	for (int n=0; n<nNode; n++) {
	    Node node = serviceListNode.getNode(n);
	    if (Service.isServiceNode(node) == false)
		continue;
	    Service service = new Service(node);
	    serviceList.add(service);
	} 
	return serviceList;
    }
    
    public boolean loadDescription(File file) throws InvalidDescriptionException {
	try {
	    Parser parser = UPnP.getXMLParser();
	    rootNode = parser.parse(file);
	    if (rootNode == null)
		throw new InvalidDescriptionException(Description.NOROOT_EXCEPTION, file);
	    deviceNode = rootNode.getNode(Device.ELEM_NAME);
	    if (deviceNode == null)
		throw new InvalidDescriptionException(Description.NOROOTDEVICE_EXCEPTION, file);
	} catch (ParserException e) {
	    throw new InvalidDescriptionException(e);
	}
	setDescriptionFile(file);
	
	return true;
    }
    
    private void setDescriptionFile(File file)
    {
	getDeviceData().setDescriptionFile(file);
    }
    
    private DeviceData getDeviceData()
    {
	Node node = deviceNode;
	DeviceData userData = (DeviceData)node.getUserData();
	if (userData == null) {
	    userData = new DeviceData();
	    node.setUserData(userData);
	    userData.setNode(node);
	}
	return userData;
    }
    
} // Interface
