#include "osdcontroller.h"
#include "thread.h"

namespace NonInteractiveOsdPatch
{

  class cListenerListObject : public cListObject
  {
  public:
    cListenerListObject(int priority, cOsdListener* listener);
    bool operator< (const cListObject &ListObject);

    int iPriority;
    cOsdListener* iListener;
  };

  cListenerListObject::cListenerListObject(int priority, cOsdListener* listener)
    : cListObject(),iPriority(priority), iListener( listener )
  {
  }
  bool cListenerListObject::operator< (const cListObject &ListObject)
  {
    
    return iPriority > ((cListenerListObject *)&ListObject)->iPriority;
  }

  cOsdController OsdController;
  
  cOsdController::cOsdController()
    : iShowing( false )
  {
    iMutex = new cMutex();
    iListeners = new cList<cListenerListObject>;
  }

  cOsdController::~cOsdController()
  {
    delete iListeners;
    delete iMutex;
  }

  bool cOsdController::Subscribe(  int priority, cOsdListener* listener )
  {
   
    cMutexLock( iMutex );
    if ( !listener )
      return false;
    
    for ( cListenerListObject* llo = iListeners->First();
	  llo; llo = iListeners->Next(llo))
    {
      // check for duplicates
      if ( llo->iListener == listener )
	return false;
    }

    cListenerListObject *lo = new cListenerListObject(priority, listener);
    iListeners->Add( lo );
    iListeners->Sort();

    // Give osd to the new listener if it has higher priority
    // than the current one
    if ( iShowing && !iCurrent )
    {
      listener->Show();
      iCurrent = lo;
    }
    else if ( iShowing && iCurrent && iCurrent->iPriority < priority )
    {
      iCurrent->iListener->Hide();
      ShowHighest();

    }
    
    return true;
  }

  void cOsdController::Unsubscribe( cOsdListener* listener )
  {
    cMutexLock( iMutex );
    if ( !listener )
      return;

    for ( cListenerListObject* llo = iListeners->First();
	  llo; llo = iListeners->Next(llo))
    {

      if ( llo->iListener == listener )
      {
	iListeners->Del( llo, true );
	if ( iShowing && llo == iCurrent )
	{
	  listener->Hide();
	  ShowHighest();
	}
	break;
      }
    }

  } 

  void cOsdController::Show()
  {
    cMutexLock( iMutex );
    iShowing = true;
    ShowHighest();

  }
  
  void cOsdController::Hide()
  {
    cMutexLock( iMutex );
    iShowing = false;
    if ( iCurrent )
      iCurrent->iListener->Hide();
    iCurrent = NULL;
  }

  void cOsdController::ShowHighest()
  {

    cListenerListObject* llo = iListeners->First();

    if ( llo )
      llo->iListener->Show();

    iCurrent = llo;

  }


}
