#include "MGEventDispMain.h"

#include <TSystem.h>        // gSystem

#include <TGTab.h>          // TGTab
#include <TGMenu.h>         // TGPopupMenu
#include <TGButton.h>       // TGTextButton
#include <TGMsgBox.h>       // TGMsgBox
#include <TGListBox.h>      // TGListBox
#include <TGFSContainer.h>  // TGFileContainer
#include <TGSplitter.h>    // TGHorizontal3DLine
#include <TGTextEntry.h> 
#include <TGLabel.h>       // TGLabel

#include "MGFadcDisp.h"

// FIXME: Move to MAGIC.h
#define S_ISDIR(m) (((m)&(0170000)) == (0040000))  

ClassImp(MGEventDispMain)

enum CommandEventDispMain {
  M_FILE_CLOSE , 
  M_BUT_DISP1_EVT, 
  M_BUT_DISP1_PED, 
  M_BUT_DISP1_CAL, 

  M_FILERESET, 
  M_PBUTTON_CDIR_UP, 
  M_PBUTTON_LIST_MODE, 
  M_PBUTTON_DETAIL_MODE 
} ; 


MGEventDispMain::MGEventDispMain(const TGWindow *p, const TGWindow *main, 
                            UInt_t w, UInt_t h ) 
        : TGTransientFrame(p, main, w, h ) 
{
  //
  //    Main window to controll the october test
  //

  //    set non-gui members to starting values 

  sprintf ( fInputFile, "\n" ) ; 

  //
  //    First create the MenuBar.   
  //

  //     Layout objects for menue. 

  fLayMenuBar = new TGLayoutHints ( kLHintsTop | kLHintsLeft | kLHintsExpandX, 2, 2, 2, 2 ) ; 
  fLayMenuItem = new TGLayoutHints ( kLHintsTop | kLHintsLeft , 0, 4, 0, 0 ) ; 
  
  //  crate the menu bar

  fFileMenu = new TGPopupMenu ( fClient->GetRoot() ) ; 
  fFileMenu->AddEntry ("Close", M_FILE_CLOSE ) ; 
  fFileMenu->Associate(this) ; 
  
  //  the button messages are handled by main frame (this) 

  fMenuBar = new TGMenuBar ( this, 1, 1, kHorizontalFrame ) ; 
  fMenuBar->AddPopup("File", fFileMenu, fLayMenuItem ) ;   
  AddFrame(fMenuBar, fLayMenuBar ) ; 
  
  fLineSep1 = new TGHorizontal3DLine(this) ; 
  AddFrame(fLineSep1, new TGLayoutHints(kLHintsTop | kLHintsExpandX) );

  
  //
  //    Create the top window with a lot of buttons 
  //

  fFrameTop = new TGCompositeFrame (this, 300,100, kVerticalFrame ) ; 
  
  fTop1 = new TGHorizontalFrame (fFrameTop, 300, 100 ) ; 

  fButFadcDispEvts = new TGTextButton(fTop1, "FADC Disp for Events", M_BUT_DISP1_EVT );
  fButFadcDispEvts->Associate(this) ;   
  fTop1->AddFrame (fButFadcDispEvts, new TGLayoutHints(kLHintsTop | kLHintsLeft, 10, 10, 5, 5) );
  
  fButFadcDispPed  = new TGTextButton(fTop1, "FADC Disp for PedEvts", M_BUT_DISP1_PED );
  fButFadcDispPed->Associate(this) ;   
  fTop1->AddFrame (fButFadcDispPed, new TGLayoutHints(kLHintsTop | kLHintsLeft, 10, 10, 5, 5) );
  
  fButFadcDispCal  = new TGTextButton(fTop1, "FADC Disp for CalEvts", M_BUT_DISP1_CAL );
  fButFadcDispCal->Associate(this) ;   
  fTop1->AddFrame (fButFadcDispCal, new TGLayoutHints(kLHintsTop | kLHintsLeft, 10, 10, 5, 5) );
  
  

  fFrameTop->AddFrame (fTop1, new TGLayoutHints(kLHintsCenterX, 10, 10, 5, 5) );

  AddFrame(fFrameTop, new TGLayoutHints (kLHintsTop ) ) ;   

  //   a line between top and low frame
  
  fLineSep2 = new TGHorizontal3DLine(this) ; 
  AddFrame(fLineSep2, new TGLayoutHints(kLHintsTop | kLHintsExpandX) );

  //
  //    Create the low window with a tabs in it
  //

  fFrameLow = new TGCompositeFrame (this, 300,100, kHorizontalFrame ) ; 
  
  fLayTab = new TGLayoutHints ( kLHintsExpandX   , 5, 5, 5, 5 ) ;

  //    create the first tab

  fTab = new TGTab ( fFrameLow, 400, 400 ) ;   

  TGCompositeFrame *tf = fTab->AddTab("Input File") ; 
  
  fTabF1 = new TGCompositeFrame (tf, 100, 100, kHorizontalFrame) ; 
  //  tf->AddFrame(fTabF1, fLayTab ) ; 

  fTabF1a = new TGCompositeFrame (tf, 100, 100, kHorizontalFrame) ; 
  tf->AddFrame(fTabF1a,  new TGLayoutHints ( kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5 ) ) ; 

  fTabF1b = new TGCompositeFrame (tf, 100, 100, kHorizontalFrame) ; 
  tf->AddFrame(fTabF1b,  new TGLayoutHints ( kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5 ) ) ; 

  fTabF1c = new TGCompositeFrame (tf, 100, 100, kVerticalFrame) ; 
  //  tf->AddFrame(fTabF1c,  new TGLayoutHints ( kLHintsTop | kLHintsLeft | kLHintsExpandX | kLHintsExpandY  , 5, 5, 5, 5 ) ) ; 
  tf->AddFrame(fTabF1c,  new TGLayoutHints ( kLHintsExpandX | kLHintsExpandY  , 5, 5, 5, 5 ) ) ; 
  
  //   the items in the first subframe

  fLabFileName = new TGLabel(fTabF1a, new TGString("selected File:") );
  fTabF1a->AddFrame( fLabFileName, new TGLayoutHints (kLHintsLeft, 10, 10, 10, 10)) ; 

  fTxtFileName = new TGTextEntry(fTabF1a, fTxtBufFileName = new TGTextBuffer(100) );
  fTxtFileName->Resize(60, fTxtFileName->GetDefaultHeight());
  fTabF1a->AddFrame(fTxtFileName, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); 

  fButFileReset = new TGTextButton (fTabF1a, "Reset", M_FILERESET ) ;
  fButFileReset->Associate(this) ; 
  fTabF1a->AddFrame (fButFileReset, new TGLayoutHints (kLHintsRight, 10, 10, 10, 10  ) ) ; 
  
  
  
  //   the items in the second subfraem

  fLabDir = new TGLabel(fTabF1b, new TGString("Directory:") );
  fTabF1b->AddFrame( fLabDir, new TGLayoutHints (kLHintsLeft, 10, 10, 10, 10)) ; 

  fDir = new TGListBox(fTabF1b, -1) ; 
  fDir->Resize(350,20) ;
  char temp[100] ; 
  //  sprintf ( temp, "%s", START_DIRECTORY ) ; 
  sprintf ( temp, "%s", gSystem->WorkingDirectory()  ) ; 
  fDir->AddEntry(temp, 1) ; 
  fTabF1b->AddFrame( fDir, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5 ) ) ; 


  fPicCdup = fClient->GetPicture("tb_uplevel.xpm") ; 
  fCdup = new TGPictureButton(fTabF1b, fPicCdup, M_PBUTTON_CDIR_UP ) ; 
  fCdup->SetToolTipText("One Level up!") ; 
  fCdup->Associate(this) ; 
  fTabF1b->AddFrame (fCdup, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 5, 5, 5) ) ; 

  fPicList = fClient->GetPicture("tb_list.xpm") ; 
  fListMode = new TGPictureButton(fTabF1b, fPicList, M_PBUTTON_LIST_MODE ) ; 
  fListMode->SetToolTipText("List Mode") ; 
  fListMode->Associate(this) ; 
  fListMode->SetState(kButtonUp) ; 
  fListMode->AllowStayDown(kTRUE) ; 
  fListMode->AllowStayDown(kTRUE) ;  fTabF1b->AddFrame (fListMode, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 5, 5, 5) ) ;

  fPicDetail = fClient->GetPicture("tb_details.xpm") ; 
  fDetail = new TGPictureButton(fTabF1b, fPicDetail, M_PBUTTON_DETAIL_MODE ) ; 
  fDetail->SetToolTipText("Details Mode") ; 
  fDetail->Associate(this) ; 
  fDetail->SetState(kButtonEngaged) ; 
  fDetail->AllowStayDown(kTRUE) ; 
  fTabF1b->AddFrame (fDetail, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 5, 5, 5) ) ; 

  // the items in the third subframe

  fFileView = new TGListView(fTabF1c, 540, 380 ) ; 
  fFileCont = new TGFileContainer(fFileView->GetViewPort(), 100, 100,
				  kVerticalFrame, fgWhitePixel) ; 

  fFileCont->Associate(this) ; 
  fFileView->GetViewPort()->SetBackgroundColor(fgWhitePixel) ; 
  fFileView->SetContainer(fFileCont) ; 
  fFileCont->SetFilter("*") ; 
  //  fFileCont->ChangeDirectory(START_DIRECTORY) ; 
  fFileCont->ChangeDirectory(gSystem->WorkingDirectory()) ; 
  fFileView->SetViewMode(kLVDetails); 
  fFileCont->Sort(kSortByName) ; 
  
  fTabF1c->AddFrame(fFileView, new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 5, 5, 5, 5) ) ; 

  tf->AddFrame(fTabF1, fLayTab) ;
 
  fFrameLow->AddFrame ( fTab, new TGLayoutHints(kLHintsBottom | kLHintsExpandX | kLHintsExpandY, 5, 5, 5, 5) ); 

  AddFrame(fFrameLow, new TGLayoutHints (kLHintsExpandX|kLHintsExpandY) ) ; 

  //
  //   Map the window, set up the layout, etc. 
  //

  SetWMSizeHints(200, 250, 1000, 1000, 10, 10 ) ;      // set the smallest and biggest size of the Main frame

  MapSubwindows();
  
  Layout();
  
  SetWindowName("EventDispMain");
  SetIconName("EventDispMain");
  
  MapWindow();

} 


// ======================================================================
// ======================================================================

MGEventDispMain::~MGEventDispMain()
{
  //delete  fPicCdup, fPicList, fPicDetail; 
  
    delete fLayTab;
    delete fLayMenuBar;
    delete fLayMenuItem;

    delete fFileView;
    delete fFileCont;

    delete fCdup;
    delete fListMode;
    delete fDetail;
    delete fDir ;
    delete fLabDir ; 

    delete fButFileReset ; 
    delete fTxtFileName  ; 
    delete fLabFileName  ; 
    
    delete fTabF1c;
    delete fTabF1b;
    delete fTabF1a;
    delete fTabF1;

    delete fButFadcDispCal; 
    delete fButFadcDispPed; 
    delete fButFadcDispEvts; 
    delete fTop1;
    delete fTab;

    delete fLineSep2 ; 
    delete fLineSep1 ; 

    delete fFrameTop;
    delete fFrameLow;

    delete fFileMenu;
    delete fMenuBar;
} 


// ======================================================================
// ======================================================================

void MGEventDispMain::CloseWindow()
{
   // Got close message for this MainFrame. Calls parent CloseWindow()
   // (which destroys the window) and terminate the application.
   // The close message is generated by the window manager when its close
   // window menu item is selected.

  delete this ; 
}


// ======================================================================
// ======================================================================

Bool_t MGEventDispMain::InputFileSelected() 
{
  //   Checks if there is a selected input root file
   
  if ( strcmp ( fInputFile, "\n") == 0 )
    { 
      return ( kFALSE ) ; 
    } 
  
  return (kTRUE) ; 
} 


// ======================================================================
// ======================================================================

Bool_t MGEventDispMain::ProcessMessage(Long_t msg, Long_t parm1, Long_t)
{     
  // Process events generated by the buttons in the frame.
  
  Int_t   buttons = 4, retval = 0 ; 
  Char_t  wort[100] ;
  Char_t  extens[5] ;
  Char_t  command[110] ;
 
  TGFileItem *item ;     // to process items in the file view container
  void *np = NULL ;      // null pointer

  switch (GET_MSG(msg)) 
    {
    case kC_COMMAND:
      switch (GET_SUBMSG(msg)) 
	{
	case kCM_BUTTON:
	  
	  switch (parm1)
	    {  

	    case M_BUT_DISP1_EVT:
	      	
	      if ( InputFileSelected() == kFALSE ) {              // it is not selected
		
		new TGMsgBox(fClient->GetRoot(), this, "ERROR!", 
			     "No Input (root) File selected!", kMBIconExclamation, buttons, &retval);
		break ; 
	      }      
	      
	      new MGFadcDisp( fInputFile , "Events", 
			      fClient->GetRoot(), this, 600, 500 ) ; 
	      break ; 
		
	    case M_BUT_DISP1_PED:
	      	
	      if ( InputFileSelected() == kFALSE ) {              // it is not selected
		
		new TGMsgBox(fClient->GetRoot(), this, "ERROR!", 
			     "No Input (root) File selected!", kMBIconExclamation, buttons, &retval);
		break ; 
	      }      
	      new MGFadcDisp( fInputFile , "PedEvts", 
			      fClient->GetRoot(), this, 600, 500 ) ; 
	      break ; 

	    case M_BUT_DISP1_CAL:
	      
	      if ( InputFileSelected() == kFALSE ) {              // it is not selected
		new TGMsgBox(fClient->GetRoot(), this, "ERROR!", 
			     "No Input (root) File selected!", kMBIconExclamation, buttons, &retval);
		break ; 
	      }      
	      
	      new MGFadcDisp( fInputFile , "CalEvts", 
			      fClient->GetRoot(), this, 600, 500 ) ; 
	      break ; 
		
	    case M_FILERESET:
	      
	      sprintf ( fInputFile, "\n" ) ; 
	      fTxtFileName->SetText( fInputFile ) ; 
	      
	      break; 

	    case M_PBUTTON_CDIR_UP :

	      //  goto the parent directory
	      
	      gSystem->ChangeDirectory("..") ; 
	      fDir->RemoveEntry(1) ; 
	      sprintf (wort, "%s", gSystem->WorkingDirectory() ) ; 
	      fDir->AddEntry(wort,1) ; 
	      fDir->MapSubwindows() ; 
	      fDir->Layout() ; 
	      fFileCont->ChangeDirectory( wort ) ; 
	      fFileCont->DisplayDirectory() ; 
	      
	      break ; 
	    
	    case M_PBUTTON_LIST_MODE:
	      fFileView->SetViewMode(kLVList) ; 
	      fDetail->SetState(kButtonUp) ; 
	      
	      break ; 
	      
	    case M_PBUTTON_DETAIL_MODE:
	      fFileView->SetViewMode(kLVDetails) ; 
	      fListMode->SetState(kButtonUp) ; 
	      
	      break ;
	      
	    default:
	      break ;
	    } 

	case kCM_MENU:

	  switch (parm1) {
	  case M_FILE_CLOSE:
	    CloseWindow() ; 

	    break; 
	  }
	  break ;
	  
	default:
	  break ;
	  
	}
      
    case kC_CONTAINER: 
      switch (GET_SUBMSG(msg)) {
	
	//      case kCT_ITEMCLICK:
	// 	printf ("itemclick\n"); 
	//      break; 
	
      
      case kCT_ITEMDBLCLICK: 
	//
	//  process the double click in the file view container
	//
	
	if ( parm1 == kButton1) {
	  if ( fFileCont->NumSelected() == 1 ) {   
	    //
	    //  one file selected
	    //	  
	    item = (TGFileItem *) fFileCont->GetNextSelected(&np) ; 
	    
	    if ( S_ISDIR(item->GetType()) )   // file is directory
	      {  
		//  goto directory 
		
		sprintf (wort, "%s", item->GetItemName()->GetString()) ;
		fFileCont->ChangeDirectory ( wort ) ; 
		gSystem->ChangeDirectory( wort ) ; 
		
		sprintf (wort, "%s", gSystem->WorkingDirectory() ) ; 
		fDir->RemoveEntry(1) ; 
		fDir->AddEntry( wort, 1 ) ; 
		fDir->MapSubwindows() ; 
		fDir->Layout() ; 
	      }
	    else                              // file is no directory, is a file 
	      { 
		sprintf (wort, "%s", item->GetItemName()->GetString() ) ; 
	    
		//    determine the file type by extensions
		
		for (Int_t i = 0 ; i<5; i++) 
		  extens[i] = '\0' ; 
		
		for ( Int_t i=0; wort[i] != '\0'; i++) {
		  if ( wort[i] == '.') {
		    strncpy (extens, &wort[i+1], 4 ) ; 
		    break ; 
		  }
		}
		
		if ( ! strcmp(extens, "ps") ) {              //     postscript file
		  sprintf ( command, "gv %s/%s &", 
			    gSystem->WorkingDirectory(), 
			    wort ) ; 
		  gSystem->Exec(command) ; 
		  break ; 
		}
		else if  ( ! strcmp(extens, "root") ) {      //     root file
		  sprintf ( fInputFile, "%s/%s" , gSystem->WorkingDirectory(), wort ) ;  
		  fTxtFileName->SetText( fInputFile ) ;

		  break ; 
		}
		
	      } 
	  }
	}
	break; 
	
      default:
	break ;
      }
      
      
      
    default:
      break;
    }
  return kTRUE;
} 
