package commons.ui;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import javax.swing.table.DefaultTableModel;
import basics.application.Binder;
import basics.profiler.AppHistoryListener;
import basics.profiler.AppWatcher;
import basics.profiler.InspectReportListener;
import basics.profiler.MemoryListener;
import basics.profiler.MemoryWatcher;
import basics.profiler.Profiler;
import basics.time.LongSleep;
import basics.utl.Empty;
import basics.utl.SUtl;
import basics.utl.SysUtl;
import commons.application.CommandInterpreter;
import commons.application.ctx.Context;
import commons.ui.plugin.ViewBuilder;
import commons.ui.toolbox.GU;
import commons.ui.toolbox.WaitCursorEventQueue;
import commons.ui.views.main.MainView;
import commons.ui.views.other.HistoryView;
import commons.ui.views.param.ParamView;
import commons.ui.views.script.ScriptView;

public class GGUI implements UIController, InspectReportListener, AppHistoryListener,
   MemoryListener, WindowListener
{

ViewBuilder           vb           = null;
private static String lastCtx      = "";
private static String lastMsg      = "";
private boolean       quit         = false;
CommandInputReader    inputReader  = null;
CommandInterpreter    interpreter;
MainView              mainView     = null;
ScriptView            scriptView   = null;
ParamView             paramView    = null;
HistoryView           historyView  = null;
Object                mProcessLock = new Object();
LongSleep             waitForUi    = null;

private void initView(boolean batch)
{
   EventQueue waitQueue = new WaitCursorEventQueue(300);
   Toolkit.getDefaultToolkit().getSystemEventQueue().push(waitQueue);
   vb = (ViewBuilder)Binder.createNew(ViewBuilder.class);
   JFrame mainFrame = GU.mainFrame("PILO", vb.getDimension(), this);
   GU.defaultfont(mainFrame);
   if(!batch)
   {
      inputReader = new CommandInputReader(this);
      inputReader.start();
   }
   mainView = new MainView(vb.getDimension(), vb.getLineHeight(), inputReader);
   scriptView = new ScriptView(vb.getDimension());
   paramView = new ParamView(vb.getDimension());
   historyView = new HistoryView(vb.getWidth(), vb.getLineHeight());
   JTabbedPane tabbedPane = GU.tabbedpane();
   tabbedPane.add("main", mainView.getView());
   tabbedPane.add("scripts", scriptView.getView());
   tabbedPane.add("params", paramView.getView());
   vb.addPlugins(tabbedPane);
   mainFrame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
   mainFrame.getContentPane().add(historyView.getView(), BorderLayout.SOUTH);
   Profiler.addStateListener(this);
   AppWatcher.addListener(this);
   MemoryWatcher.addListener(this);
   mainFrame.pack();
   mainFrame.setVisible(true);
   waitForUi.stop();
   mainView.inputFocus();
}

// ============================= UI CONTROLLER: output
// ===========================//
public void print(Context ctx)
{
   String msg = ctx.toString();
   if(!msg.equals(lastCtx))
   {
      lastCtx = msg;
      mainView.printContext(msg);
   }
   mainView.printError(ctx.getErrorsAsString());
}

public void print(String key, String msg)
{
   SysUtl.println("[E." + key + ">" + msg);
}

public void print(String msg)
{
   if(Empty.is(SUtl.xtrim(msg)))
      return;
   if(msg.equals(lastMsg))
      return;
   lastMsg = msg;
   mainView.appendMessage(msg);
}

// ============================= UI CONTROLLER: controller ================= //
public void registerCommandInterpreter(CommandInterpreter interpreter)
{
   this.interpreter = interpreter;
}

public void start(final boolean batch)
{
   javax.swing.SwingUtilities.invokeLater(new Runnable()
   {

      public void run()
      {
         initView(batch);
      }
   });
   if(batch)
   {
      waitForUi = new LongSleep();
      waitForUi.sleep(5000);
   }
}

public synchronized void eval(final String input)
{
   if(input.length() == 0)
      return;
   if(input.equals("quit"))
   {
      quit = true;
      System.exit(0);
      return;
   }
   synchronized(mProcessLock)
   {
      Runnable r = new Runnable()
      {

         public void run()
         {
            interpreter.process(input);
            synchronized(mProcessLock)
            {
               mProcessLock.notifyAll();
            }
         }
      };
      new Thread(r).start();
      try
      {
         mProcessLock.wait();
      }
      catch(InterruptedException ex)
      {
      }
   }
}

public boolean exit()
{
   return quit;
}

public void cls()
{
   mainView.cls();
}

public void clearInput()
{
   mainView.clearInput();
}

public String getInput()
{
   return mainView.getInput();
}

// ============================= callbacks ===========================//
public void fireCtxHasChanged(Context ctx)
{
   paramView.fireCtxHasChanged(ctx);
}

/**
 * Interface implementation for
 * @{link InspectListener}
 */
public void profilerStateEvent(DefaultTableModel t)
{
   mainView.profilerStateEvent(t);
}

public void appHistoryEvent(String msg)
{
   historyView.appHistoryEvent(msg);
}

public void memoryEvent(String msg)
{
   mainView.memoryEvent(msg);
}

// ============================= window ===========================//
public void windowClosing(WindowEvent e)
{
   scriptView.saveScript();
}

public void windowActivated(WindowEvent e)
{
}

public void windowClosed(WindowEvent e)
{
}

public void windowDeactivated(WindowEvent e)
{
}

public void windowDeiconified(WindowEvent e)
{
}

public void windowIconified(WindowEvent e)
{
}

public void windowOpened(WindowEvent e)
{
}
}
