/*## (c) SECURITY EXPLORATIONS    2018 poland                                #*/
/*##     http://www.security-explorations.com                                #*/

/* THIS SOFTWARE IS PROTECTED BY DOMESTIC AND INTERNATIONAL COPYRIGHT LAWS    */
/* UNAUTHORISED COPYING OF THIS SOFTWARE IN EITHER SOURCE OR BINARY FORM IS   */
/* EXPRESSLY FORBIDDEN. ANY USE, INCLUDING THE REPRODUCTION, MODIFICATION,    */
/* DISTRIBUTION, TRANSMISSION, RE-PUBLICATION, STORAGE OR DISPLAY OF ANY      */
/* PART OF THE SOFTWARE, FOR COMMERCIAL OR ANY OTHER PURPOSES REQUIRES A      */
/* VALID LICENSE FROM THE COPYRIGHT HOLDER.                                   */

/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS    */
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,*/
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    */
/* SECURITY EXPLORATIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF  */
/* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                                  */

import java.lang.*;
import java.util.*;
import javax.tv.service.*;
import javax.tv.service.selection.*;
import org.ocap.shared.dvr.*;

public class ServiceMonitor implements ServiceContextListener, DaemonThread.Code {
 public static final int WATCH_SERVICE   = 0x00;
 public static final int WATCH_RECORDING = 0x01;

 public static final int MAX_WATCH       = 0x02;

 public static final int EVT_PRESENTING  = 0x01;
 public static final int EVT_TERMINATED  = 0x02;

 public static final int LONG_TIME       = 0x7fffffff;

 private static ServiceMonitor instance;
 private static boolean running;

 private static int last_type;
 private static Service last_service;

 private static Vector watches[];

 private static Mutex wtch_access;

 static {
  watches=new Vector[MAX_WATCH];

  for(int i=0;i<MAX_WATCH;i++) {
   watches[i]=new Vector();
  }

  wtch_access=new Mutex();
 }

 private ServiceMonitor() {
 }

 public void process_watches(int type,int event,Service srv) {
  Vector wtch_vector=watches[type];

  if (wtch_vector.size()==0) return;

  watch_lock();

  for(int j=0;j<wtch_vector.size();j++) {
   ServiceWatch watch=(ServiceWatch)wtch_vector.elementAt(j);
   watch.action(type,event,srv);
  }

  watch_unlock();
 }

 public void receiveServiceContextEvent(ServiceContextEvent ev) {
  try {
   ServiceContext ctx=ev.getServiceContext();
   Service srv=ctx.getService();

   Output.text("event: "+ev); 

   int type=-1;
   int event=-1;

   if (srv!=null) {
    if (srv instanceof RecordedService) {
     type=WATCH_RECORDING;
    } else {
     type=WATCH_SERVICE;
    }


    if (ev instanceof NormalContentEvent) {
     event=EVT_PRESENTING;

     process_watches(type,event,srv);

     if (type>=0) {
      last_type=type;
      last_service=srv;
     }
    }
   } else {
    if (ev instanceof PresentationTerminatedEvent) {
     event=EVT_TERMINATED;

     if (last_service!=null) {
      process_watches(last_type,event,last_service);

      last_type=-1;
      last_service=null;
     }
    }
   }
  } catch(Throwable t) {}
 }

 public static void watch_lock() {
  wtch_access.lock();
 }

 public static void watch_unlock() {
  wtch_access.unlock();
 }

 public static boolean has_watch(String name) {
  for(int i=0;i<watches.length;i++) {
   Vector wtch_vector=watches[i];

   for(int j=0;j<wtch_vector.size();j++) {
    ServiceWatch wtch=(ServiceWatch)wtch_vector.elementAt(j);
    if (wtch.name().equals(name)) return true;
   }
  }

  return false;
 }

 public static boolean add_watch(ServiceWatch watch) {
  boolean res=false;

  watch_lock();

  if (!has_watch(watch.name())) {
   int type=watch.type();

   if ((type>=0)&&(type<MAX_WATCH)) {
    watches[type].addElement(watch);
    res=true;
   }
  }

  watch_unlock();

  return res;
 }

 public void run(Object args[]) {
  running=true;

  ServiceContext ctx=ServiceContextFactory.getInstance().getServiceContexts()[0];
  ctx.addListener(this);
  
  while(running) {
   Utils.sleep(LONG_TIME);
  }
 }

 public static void start() {
  if (instance==null) {
   instance=new ServiceMonitor();
  }

  DaemonThread.start(instance,null);
 }
}
