// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.

#ifndef toolx_Xt_session
#define toolx_Xt_session

#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>

#include <ostream>

namespace toolx {
namespace Xt {

class session {
public:
  session(std::ostream& a_out)
  :m_out(a_out),m_app_context(0),m_app_widget(0),m_app_owner(false)
  {}
  session(std::ostream& a_out,XtAppContext a_app_context,Widget a_app_widget)
  :m_out(a_out),m_app_context(a_app_context),m_app_widget(a_app_widget),m_app_owner(false)
  {}
  session(std::ostream& a_out,int& a_argc,char** a_argv)
  :m_out(a_out),m_app_context(0),m_app_widget(0),m_app_owner(false)
  {
  //LookDSM_Problem();
    Arg args[1];
    XtSetArg(args[0],XtNgeometry,XtNewString("100x100"));
    m_app_widget = ::XtAppInitialize(&m_app_context,"toolx::Xt::session",NULL,(Cardinal)0,&a_argc,a_argv,NULL,args,1);
    if(!m_app_context || !m_app_widget) {
      m_app_context = 0;
      m_app_widget = 0;
      m_app_owner = false;
      return;
    }
    m_app_owner = true;
  }
  virtual ~session() {
    if(m_app_owner) {
      if(m_app_widget) {::XtDestroyWidget(m_app_widget);m_app_widget = 0;}
      if(m_app_context) {::XtDestroyApplicationContext(m_app_context);m_app_context = 0;}
    }
  }
protected:
  session(const session& a_from)
  :m_out(a_from.m_out),m_app_context(0),m_app_widget(0),m_app_owner(false)
  {}
  session& operator=(const session&){return *this;}
public:
  std::ostream& out() const {return m_out;}
  bool is_valid() {return m_app_context && m_app_widget?true:false;}
  bool steer() {
    if(!m_app_context) return false;
    while(true) {
      XEvent event;
      ::XtAppNextEvent(m_app_context,&event);
      ::XtDispatchEvent(&event);
      //if(m_exit) break;
    }
    return true;
  }
  bool sync() {
  //if(!m_app_widget) return false;
  //Display* display = XtDisplay(m_app_widget);
  //::XSync(display,False);
    if(!m_app_context) return false;
    while(true) { 
      XtInputMask input = ::XtAppPending(m_app_context);
      if(input==0) break;
      XEvent event;
      ::XtAppNextEvent(m_app_context,&event);
      ::XtDispatchEvent(&event);        
    }
    return true;
  }
public:
  Widget get_app_widget() {return m_app_widget;}
protected:
  std::ostream& m_out;
  XtAppContext m_app_context;
  Widget m_app_widget;  
  bool m_app_owner;
};

}}


#endif
