package basics.gui;

import static basics.gui.toolkit.GU.defaultfont;
import static basics.gui.toolkit.GU.mainFrame;
import static basics.gui.toolkit.GU.tabbedpane;
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.gui.toolkit.CommandInputReader;
import basics.gui.toolkit.CommandInterpreter;
import basics.gui.toolkit.UIController;
import basics.gui.toolkit.ViewBuilder;
import basics.gui.toolkit.WaitCursorEventQueue;
import basics.utl.Empty;
import basics.utl.SUtl;

public class GConsole implements WindowListener, UIController
{
private CommandInputReader inputReader  = null;
private CommandInterpreter interpreter;
private MainView           mainView     = null;
private Object             mProcessLock = new Object();
private boolean            quit         = false;
private boolean            NOREPEAT     = false;
private static String      lastMsg      = "";

public static void main(String [] args)
{
   new GConsole(new InterpreterMock(), new ViewDefSample());
}

public GConsole(CommandInterpreter interpreter, final ViewBuilder vb)
{
   javax.swing.SwingUtilities.invokeLater(new Runnable()
   {
      public void run()
      {
         initView(vb);
      }
   });
   registerCommandInterpreter(interpreter);
}

private void initView(ViewBuilder vb)
{
   EventQueue waitQueue = new WaitCursorEventQueue(300);
   Toolkit.getDefaultToolkit().getSystemEventQueue().push(waitQueue);
   JFrame mainFrame = mainFrame("Q", vb.getDimension(), this);
   defaultfont(mainFrame);
   inputReader = new CommandInputReader(this);
   inputReader.start();
   mainView = new MainView(vb.getDimension(), vb.getLineHeight(), inputReader);
   JTabbedPane tabbedPane = tabbedpane();
   tabbedPane.add("main", mainView.getView());
   vb.addPlugins(tabbedPane);
   mainFrame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
   mainFrame.pack();
   mainFrame.setVisible(true);
   mainView.inputFocus();
}

//========================= interface methods ==============================//
public void print(String key, String msg)
{
   print(key + ">" + msg);
}

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

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

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 ===========================//
/**
 * Interface implementation for
 * @{link InspectListener}
 */
public void profilerStateEvent(DefaultTableModel t)
{
   //   mainView.profilerStateEvent(t);
}

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

// ============================= window ===========================//
public void windowClosing(WindowEvent e)
{
}

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)
{
}
}
