/* 
 * 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.importer.core.event.structs;


import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;

import org.cybergarage.upnp.Service;

import org.osgi.service.upnp.UPnPEventListener;

import org.apache.felix.upnp.basedriver.importer.core.MyCtrlPoint;
import org.apache.felix.upnp.basedriver.importer.core.event.message.FirstMessage;
import org.apache.felix.upnp.basedriver.importer.core.event.message.ListenerModified;

/* 
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/

public class Monitor {
	private Hashtable sidStateVars;
	private SidsListenersMaps sidListSid;

	public Monitor() {
		this.sidListSid = new SidsListenersMaps();
		this.sidStateVars = new Hashtable();
	}

	public synchronized void putStateVars(String sid, StateVarsToNotify vars) {
		sidStateVars.put(sid, vars);
		Vector listeners = (Vector) sidListSid.getListenersFromSid(sid);
		if (listeners != null) {
			sidListSid.updateListeners(sid, vars.getDeviceID(), vars.getServiceID(), vars.getDictionary());
			sidListSid.setAlreadyFirst(sid,true);
		} else {
			sidListSid.setAlreadyFirst(sid, false);
		}
	}
	public synchronized void updateStateVars(String sid, Dictionary dic) {
		StateVarsToNotify vars = (StateVarsToNotify) sidStateVars.get(sid);
		if (vars != null) {
			vars.updateDic(dic);
			if (sidListSid.getAlreadyFirst(sid)) {
			    /*
			     * Sends only the changed StateVariable
			     */
				sidListSid.updateListeners(sid, 
				        vars.getDeviceID(), vars.getServiceID(), 
				        dic);
			} else {
			    /*
			     * Sends the sholw StateVariable for the service 
			     */
				boolean bool = sidListSid.updateListeners(sid, 
				        vars.getDeviceID(), vars.getServiceID(), 
				        vars.getDictionary());
				if (bool) {
					sidListSid.setAlreadyFirst(sid,true);
				}
			}
		}
	}
    
/*    
    public synchronized StateVarsToNotify getStateVars(String sid) {
        return (StateVarsToNotify) sidStateVars.get(sid);
    }
    public synchronized void removeStateVars(String sid) {
        sidStateVars.remove(sid);
    }
*/
	public synchronized void addListener(String sid, UPnPEventListener listener) {
		StateVarsToNotify vars = (StateVarsToNotify) sidStateVars.get(sid);
		if (vars != null) {
		    /*
		     * Notify the listener whit the whole StateVariables and then
		     * the next time you send only the changed StateVariables
		     */
            listener.notifyUPnPEvent(vars.getDeviceID(), 
                    vars.getServiceID(),vars.getDictionary());
        }
		sidListSid.putSid2Listeners(sid, listener);
		sidListSid.putListener2Sids(listener, sid);
	}

	/**
	 * Delete the reference to the listener from the stuctures sid2Listeners and listener2Sids.
	 * Also if no more listner are listening for a UPnP Service that UPnP Service is unscribed.
	 * 
	 * @param listener The listener to delete
	 * @param ctrl Needed for reference
	 */
	public synchronized void delListener(UPnPEventListener listener,
			MyCtrlPoint ctrl/*##renew, SidRenewer sidRenewer*/) {
        
        //francesco-renew
        // State variable clean up -- todo?
        
		Vector sids = sidListSid.getSidsFromListener(listener);
		if (sids != null) {
		    Iterator i = sids.iterator();
			while(i.hasNext()){
			    String sid = (String) i.next();
				Vector listeners = 
                    sidListSid.getListenersFromSid(sid);
				listeners.remove(listener);
				if (listeners.size() == 0) {
					Service service = 
                        ctrl.serviceFromSid(sid);
					//##renew  Renewer renewer = sidRenewer.get((String) sids.elementAt(i));
					//##renew  renewer.stop();
					if (service != null) {
						boolean ok = ctrl.unsubscribe(service);
						if (!ok) {
						    //TODO Log?s
							service.clearSID();
						}
					}
					sidListSid.setAlreadyFirst(sid,false);
					sidStateVars.remove(sid);
					i.remove();
				}
			}
			sidListSid.removeListenerKey(listener);			
		}
	}

	public synchronized void updateListener(ListenerModified msg,
			SubscriptionQueue subqueue, MyCtrlPoint ctrl/*##renew, SidRenewer sidRenewer*/) {
		UPnPEventListener listener = msg.getListener();
		Vector newServices = msg.getNewServices();
		Vector subscribed = new Vector();
		Vector notSubscribed = new Vector();
		
		for (int i = 0; i < newServices.size(); i++) {
			Service ser = (Service) newServices.elementAt(i);
			if (ser.isSubscribed()) {
				subscribed.add(ser);
			} else {
				notSubscribed.add(ser);
			}
		}
		

		Vector oldSids = sidListSid.getSidsFromListener(listener);
        // francesco-renew
        // check subscribed services
		if(oldSids==null) return;
		
		for (int i = 0; i < notSubscribed.size(); i++) {
			Service ser = (Service) notSubscribed.elementAt(i);
			subqueue.enqueue(new FirstMessage(ser, listener));
		}
		
		for (int i = 0; i < oldSids.size(); i++) {
			String oldSid = (String) oldSids.elementAt(i);
			if (!subscribed.contains(oldSid)) {
                // francesco-renew
                // to check -- Listner removal from sid2Listener
                				
				unsubscribeListenerForSid(oldSid,listener,ctrl);
			}
		}

	}
    
	/**
	 * Unregister the listener as UPnPListener for the UPnPService with
	 * the spicfied SID
	 * 
     * @param sid
     * @param listener
     * @param ctrl
     */
    private void unsubscribeListenerForSid(String sid, UPnPEventListener listener, MyCtrlPoint ctrl) {
        Vector listeners = sidListSid.getListenersFromSid(sid);
        listeners.remove(listener);
        if(listeners.size()==0){
			Service service = ctrl.serviceFromSid(sid);
			if (service != null) {
				boolean ok = ctrl.unsubscribe(service);
				if (!ok) {
				    //TODO Log?
					service.clearSID();
				}
			}
			sidListSid.setAlreadyFirst(sid,false);
			sidStateVars.remove(sid);
		}
        Vector sids = sidListSid.getSidsFromListener(listener);
        sids.remove(sid);
        if(sids.size()==0){
            sidListSid.removeListenerKey(listener);
        }
    }

    public synchronized void delSid(String sid) {
		Vector listeners = sidListSid.getListenersFromSid(sid);
		if(listeners==null)return;
		for (int i = 0; i < listeners.size(); i++) {
			Vector sids = sidListSid.getSidsFromListener((UPnPEventListener) listeners
					.elementAt(i));
			sids.remove(sid);
		}
		sidListSid.removeSidKey(sid);
	}

	public synchronized void clearAll(String sid, Service service) {
		service.clearSID();
		delSid(sid);
		sidStateVars.remove(sid);
	}

}
