/* 
 * 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.felix.upnp.basedriver.export;


import java.io.File;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;

import org.cybergarage.upnp.Device;
import org.cybergarage.upnp.DeviceList;
import org.cybergarage.upnp.ServiceList;
import org.cybergarage.upnp.UPnP;

import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.upnp.UPnPDevice;
import org.osgi.service.upnp.UPnPEventListener;

import org.apache.felix.upnp.basedriver.Activator;

/* 
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class ThreadExporter implements Runnable,ServiceListener {

	private boolean end;

	private RootDeviceExportingQueue queueRootDevice;

//	private String basePath; twa: redundant

//	private File baseFile; twa: redundant

	private Hashtable exportedDevices;
	
	private boolean listening;
	
	private class ExportedDeviceInfo{
		private Device device;
		private ServiceRegistration serviceRegistration;
		//private DeviceNode deviceNode;
		
			
		/**
		 * @param device
		 * @param serviceRegistration
		 * @param deviceNode
		 */
		private ExportedDeviceInfo(Device device,
				ServiceRegistration serviceRegistration,
				DeviceNode deviceNode) {
			super();
			this.device = device;
			this.serviceRegistration = serviceRegistration;
			//this.deviceNode = deviceNode;
		}
		
		
		private Device getDevice() {
			return this.device;
		}
		private ServiceRegistration getServiceRegistration() {
			return this.serviceRegistration;
		}
		/*private DeviceNode getDeviceNode(){
			return this.deviceNode;
		}*/
        
		
	}
	
	/**
	 *  
	 */
	public ThreadExporter(RootDeviceExportingQueue queue) throws InvalidSyntaxException {
	    end=false;
	    queueRootDevice=queue;
//		basePath="./tmp/device"; twa: redundant
//		baseFile = Activator.bc.getDataFile("./tmp/device"); twa: redundant
//		if(!baseFile.exists())	baseFile.mkdirs(); twa: redundant
		this.exportedDevices=new Hashtable();
		setListening(false);
		UPnP.setEnable(UPnP.USE_ONLY_IPV4_ADDR);		
	}
	public void run() {
		
		File osgiRoot = Activator.bc.getDataFile("");
		if (osgiRoot == null) {
			Activator.logger.ERROR("Unable to use filesystem");
			while (true) {
				try {
					Activator.bc.getBundle().stop();
					break;
				} catch (BundleException e) {
					e.printStackTrace();
					try {
						Thread.sleep(1000);
					} catch (InterruptedException ex) {
						ex.printStackTrace();
					}
				}
			}
			return;
		}
		
		ServiceReference rootDevice = null;
		while (!shouldEnd()) {
			DeviceNode dn = queueRootDevice.getRootDevice();
			if (dn == null)
				continue;
			rootDevice = dn.getReference();
			if(!getListening()) 
				setListen();
			Activator.logger.INFO("[Exporter] Exporting device "+ rootDevice.getProperty(UPnPDevice.FRIENDLY_NAME));
			/*
			File xml = new File(baseFile, 
					Converter.sanitizeFilename(
						(String) rootDevice.getProperty(UPnPDevice.UDN)
					)
				);
			if (xml == null)
				continue;			
			if (!xml.exists())
				xml.mkdir();

			FileOutputStream fos = null;
			try {
				fos = new FileOutputStream(xml.getAbsolutePath()
						+ File.separator + "desc.xml");
			} catch (FileNotFoundException e) {				
				Activator.logger.log(LogService.LOG_ERROR,"Unable to write:" + xml.getAbsolutePath(), e);
				continue;
			}
			if (fos == null)
				continue;*/
			/*
			 * I don't know if the exporting should be make default language of the framework
			 * or without any lanuguages
			Root r = new Root(rootDevice, context, context
					.getProperty(Constants.FRAMEWORK_LANGUAGE));
					*/
            
			synchronized (this) {
				//Root r = new Root(rootDevice, Activator.bc, null);
				/*
				 * Now that I have XML I'm going to exporting device
				 * so I have to avoid rece condition with deregistration 
				 * of the same device
				 */
				/*
				try {
					r.writeXML(fos);
				} catch (IOException e) {
					e.printStackTrace();
					continue;
				}
				if(writeXMLService(xml.getAbsolutePath(),r.getRootDevice())){
					Device d = null;
					try {
						d = new Device(xml.getAbsolutePath()
								+ File.separator + "desc.xml");
					} catch (InvalidDescriptionException e) {
						e.printStackTrace();
					}*/
					Device d = BuildDevice.createCyberLinkDevice(dn.getReference());
					if (d != null) {
						if(!bindInvokes(d,rootDevice)){
							Activator.logger.DEBUG("Unable to find all the sub device or to set action listener");
							continue;
						}
						ServiceRegistration listenReg = bindSubscribe(d);
						if(listenReg==null){
							Activator.logger.DEBUG("Unable to set action listener event listener");
							continue;
						}			
						//makeIcons(r.getRootDevice(),xml.getAbsolutePath());
						d.start();
						exportedDevices.put(
								rootDevice.getProperty(UPnPDevice.UDN),
								new ExportedDeviceInfo(d,listenReg,dn)
						);
					}
				//}
			}
		}
	}

	/**
	 * 
	 */
	private void setListen() {
		{
			try {
				Activator.bc.addServiceListener(
						this,
						// fixed by Matteo and Francesco 21/9/04
						"(&("+Constants.OBJECTCLASS+"="+UPnPDevice.class.getName()+")" 
						+ "(" + UPnPDevice.UPNP_EXPORT +"=*))"
				);
			} catch (InvalidSyntaxException ingnore) {}
		}
	}
	/*
	/**
	 * @param upnpDev
	 * @param refDev
	 *
	private void makeIcons(
			org.apache.felix.upnpbase.export.xml.Device upnpDev, 
			String path) {
		Icon[] icons = upnpDev.getIcons();
		if(icons!=null){
			byte[] buf = new byte[512];
			for (int i = 0; i < icons.length; i++) {
				try {
					String icoPath = path+icons[i].getUrl().replace('/',File.separatorChar);
					InputStream is = icons[i].getInputStream();
					Converter.makeParentPath(icoPath);
					FileOutputStream fos = new FileOutputStream(icoPath);
					int n=is.read(buf,0,buf.length);
					while(n>0){
						fos.write(buf,0,n);
						n=is.read(buf,0,buf.length);
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		org.apache.felix.upnpbase.export.xml.Device[] devs = upnpDev.getDevices();
		if(devs==null)
			return;
		for (int i = 0; i < devs.length; i++) {
			makeIcons(devs[i],path);
		}
	}*/
	/**
	 * This method is used to connect all the Action that are shown to UPnP world
	 * by CyberLink UPnP Device to the real implementation that is conatined iniside
	 * the OSGi service.
	 * This method will connect even all the subdevice of te given OSGi device.
	 * 
	 * @param d CyberLink Device that will be used associated to the OSGi Device
	 * @param rootDevice ServiceReference to the OSGi Device that will be used as 
	 * 	implementation of the CyberLink Device
	 * @return true if and only if the binding off all the action of all the children
	 * 		device is done succesfully
	 */
	private boolean bindInvokes(Device d, ServiceReference rootDevice) {
		bindInvoke(d,rootDevice);
		//Activator.bc.ungetService(rootDevice);
		ServiceReference[] childs = null;
		try {
			childs = Activator.bc.getServiceReferences(
				UPnPDevice.class.getName(),
				"("+UPnPDevice.PARENT_UDN+"="+rootDevice.getProperty(UPnPDevice.UDN)+")"
			);
		} catch (InvalidSyntaxException e) {
			e.printStackTrace();				
		}		
		String[] childsUDN = (String[]) rootDevice.getProperty(UPnPDevice.CHILDREN_UDN);
		if((childs==null)&&(childsUDN==null)){
			return true;			
		}else if((childs==null)||(childsUDN==null)){
			return false;
		}else if(childs.length==childsUDN.length){
            /*--- your code ---            
            for (int i = 0; i < childs.length; i++) {
                if(!bindInvokes(d,childs[i]))
                    return false;
            }           
            ----- your code end ---*/
            /*--- twa code ---*/
            DeviceList dl = d.getDeviceList();
            for (int i = 0; i < childs.length; i++) {
                Device dev = (Device)dl.elementAt(i);
                if(!bindInvokes(dev,childs[i]))
                    return false;
            }
            /*----- twa code end ---*/

			return true;
		}else{
			return false;
		}
			
	}
	/*
	/**
	 * @param path
	 *
	private boolean writeXMLService(String path,org.apache.felix.upnpbase.export.xml.Device d) {
		Vector v = new Vector();
		v.add(d);
		while(v.size()!=0){
			d=(org.apache.felix.upnpbase.export.xml.Device) v.elementAt(0);
			v.remove(0);
			Service[] servs = d.getServices();
			if(servs==null)
				continue;
			for (int i = 0; i < servs.length; i++) {
				FileOutputStream fos;
				String xmlPath=path+servs[i].getScpdURL().replace('/',File.separatorChar);
				if(!Converter.makeParentPath(xmlPath)) return false;
				try {
					fos = new FileOutputStream(xmlPath);
				} catch (FileNotFoundException e) {
					e.printStackTrace();
					return false;
				}
				try {
					servs[i].writeXML(fos);
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			org.apache.felix.upnpbase.export.xml.Device[] subs = d.getDevices();
			if(subs==null){
				return true;
			}else{
				for(int i = 0; i < subs.length;i++){
					v.add(subs[i]);
				}
			}
		}
		return true;
	}*/
	/**
	 * This method add an UPnPEventListener Service to the OSGi Framework so that
	 * the Base Driver can notify all the event listener registered on the CyberLink
	 * UPnP device from the UPnP World. 
	 * 
	 * @param d Device of CyberLink that will be notified by the changing of the StateVariable
	 * 		that happen on the OSGi World  
	 * @return ServiceRegistration of the new registered service.
	 */
	private ServiceRegistration bindSubscribe(Device d) {
		ExporterUPnPEventListener eventer = new ExporterUPnPEventListener(d);
		Properties p = new Properties();

		StringBuffer sb = new StringBuffer("(|");
		Vector v = new Vector();
		v.add(d);
		Device current;
		while (v.size() != 0) {
			current = (Device) v.elementAt(0);
			v.remove(0);
			DeviceList dl = current.getDeviceList();
			for (int i = 0; i < dl.size(); i++) {
				v.add(dl.elementAt(i));
			}
			sb.append("(").append(UPnPDevice.ID).append("=").append(
					current.getUDN()).append(")");
		}
		sb.append(")");
		Filter f = null;
		try {
			f = Activator.bc.createFilter(sb.toString());
		} catch (InvalidSyntaxException e) {
			e.printStackTrace();
			return null;
		}
		if (f != null) p.put(UPnPEventListener.UPNP_FILTER, f);
		
		return Activator.bc.registerService(UPnPEventListener.class.getName(), eventer, p);
	}

	/**
	 * This method do the real connection between OSGi UPnP Service action and 
	 * CyberLink UPnP Device action
	 * 
	 * @param upnpDev the CyberLink UPnP Device object that will be connected
	 * @param osgiDev the ServiceReference to OSGi UPnP Service that will be connected to
	 * 		CyberLink UPnP as implementation of the Action
	 * @return true if and only if the binding off all the action is done succesfully 
	 */
	private boolean bindInvoke(Device upnpDev,ServiceReference osgiDev) {
		ServiceList sl = upnpDev.getServiceList();
		int l=sl.size();
		for (int i = 0; i < l; i++) {
			sl.getService(i).setActionListener(
				new GeneralActionListener(
					osgiDev,
					sl.getService(i).getServiceID()
				)
			);			
		}
		return true;
	}

	/**
	 *  
	 */
	public synchronized void cleanUp() {
		Activator.logger.INFO("Cleaning...");
		
		Enumeration keys;
		
		Activator.logger.INFO("Removing temporary listener....");
		keys=exportedDevices.keys();
		while (keys.hasMoreElements()) {
			ServiceRegistration sr = ((ExportedDeviceInfo) 
					exportedDevices.get(keys.nextElement())).getServiceRegistration();
			sr.unregister();
		}		
		Activator.logger.INFO("Done");
		
		Activator.logger.INFO("Removing device....");
		keys=exportedDevices.keys();
		while (keys.hasMoreElements()) {
			Device dev = ((ExportedDeviceInfo) 
					exportedDevices.get(keys.nextElement())).getDevice();
			dev.stop();
		}		
		Activator.logger.INFO("Done");
	}

	private synchronized boolean shouldEnd() {
		return end;
	}

	public synchronized void end() {
		end = true;
		queueRootDevice.addRootDevice(null);
	}
	/**
	 * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
	 */
	public void serviceChanged(ServiceEvent event) {
		switch(event.getType()){
			case ServiceEvent.REGISTERED:break;
			
			case ServiceEvent.MODIFIED:
			case ServiceEvent.UNREGISTERING:{
				this.unexportDevice(event.getServiceReference());
				if(exportedDevices.size()==0){
					Activator.bc.removeServiceListener(this);
					setListening(false);
				}
			}break;
		}
	}
	/**
	 * @param b
	 */
	private synchronized void setListening(boolean b) {
		listening=b;	
	}
	
	private synchronized boolean getListening(){
		return listening;
	}
	
	/**
	 * @param property
	 */
	private synchronized void unexportDevice(ServiceReference dev) {
		String udn=(String) dev.getProperty(UPnPDevice.PARENT_UDN);
		if(udn==null){
			ExportedDeviceInfo edi =
				(ExportedDeviceInfo) exportedDevices.get(
					dev.getProperty(UPnPDevice.UDN)
				);
			Device d = edi.getDevice();
			if(d!=null) {
                Activator.logger.INFO("[Exporter] removing device:" +d.getFriendlyName());
				d.stop();
				exportedDevices.remove(d.getUDN());
			}
			ServiceRegistration srListener=edi.getServiceRegistration();
			if(srListener!=null) srListener.unregister();
			
		}else{
			ServiceReference[] servs=null;
			try {
				servs = Activator.bc.getServiceReferences(
						UPnPDevice.class.getName(),
						"("+UPnPDevice.UDN+"="+udn+")"
				);
			} catch (InvalidSyntaxException ignored) {}
			if(servs==null) return;
			this.unexportDevice(servs[0]);
		}
	}
}
