package commons.ui.views.script;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.undo.UndoManager;
import basics.filesystem.file.FileInfo;
import basics.filesystem.file.FileUtl;
import basics.filesystem.file.LineReader;
import basics.filesystem.model.FileModelUtl;
import basics.unexpected.Failure;
import basics.utl.Empty;
import basics.utl.FormatterUtl;
import basics.utl.SysUtl;
import commons.application.Application;
import commons.ui.toolbox.GU;
import commons.utl.CtxUtl;
public class ScriptController // implements TreeSelectionListener
{

DefaultMutableTreeNode scriptRootNode = null;
JTree                  tree           = null;
ScriptDocument         doc            = null;
JTextComponent         editor         = null;
UndoManager            manager        = null;
MouseListener          treemouse      = null;
KeyListener            treekey        = null;
KeyListener            editkey        = null;
FileInfo               currentFile    = null;
TreeSelectionListener  treeListener   = null;
String                 searchText     = "";
int                    findPosition   = -1;

private void load (String sortBy)
{
   scriptRootNode = new DefaultMutableTreeNode("scripts");
   if (sortBy.equals("size")) FileModelUtl.readFolderSortedBySize(scriptRootNode, CtxUtl.scriptSpace(Application.ctx()));
   else if (sortBy.equals("date")) FileModelUtl.readFolderSortedByDate(scriptRootNode, CtxUtl.scriptSpace(Application.ctx()));
   else FileModelUtl.readFolder(scriptRootNode, CtxUtl.scriptSpace(Application.ctx()));
   if (tree == null)
   {
      tree = GU.jtree(scriptRootNode, 0, 0, treekey, treemouse);
      tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
      tree.addTreeSelectionListener(treeListener);
   }
   else
   {
      TreeModel model = new DefaultTreeModel(scriptRootNode);
      tree.setModel(model);
   }
}

public JTree getTree ()
{
   return tree;
}

public ScriptController(JTextComponent editor)
{
   this.editor = editor;
   this.manager = new UndoManager();
   editor.getDocument().addUndoableEditListener(manager);
   // manager.undo();
   treemouse = new MouseAdapter()
   {

      public void mousePressed (MouseEvent e)
      {
         int selRow = tree.getRowForLocation(e.getX(), e.getY());
         TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
         if (selRow != -1)
         {
            if (e.getClickCount() == 1)
            {
               mySingleClick(selRow, selPath);
            }
            else if (e.getClickCount() == 2)
            {
               myDoubleClick(selRow, selPath);
            }
         }
      }
   };
   treekey = new KeyAdapter()
   {

      public void keyPressed (KeyEvent e)
      {
         if (e.isMetaDown())
         {
            if (e.getKeyCode() == 83) load("size");
            else if (e.getKeyCode() == 68) load("date");
            else if (e.getKeyCode() == 78) load("name");
         }
      }
   };
   editkey = new KeyAdapter()
   {

      public void keyPressed (KeyEvent e)
      {
         if (e.isMetaDown())
         {
            if (e.getKeyCode() == 70) find();
            else if (e.getKeyCode() == 71) findNext();
            else if (e.getKeyCode() == 83) save(true);
         }
      }
   };
   treeListener = new TreeSelectionListener()
   {

      public void valueChanged (TreeSelectionEvent e)
      {
         DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
         open(node);
      }
   };
   editor.addKeyListener(editkey);
   load("name");
}

void mySingleClick (int selRow, TreePath selPath)
{
   if (currentFile == null || selPath == null || !currentFile.getNameOnly().equals(selPath.getLastPathComponent()))
   {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
      open(node);
   }
   else
   {
      try
      {
         reformat();
         save();
      }
      catch (BadLocationException e)
      {
         e.printStackTrace();
      }
   }
}

void open (DefaultMutableTreeNode node)
{
   if (node == null || !(node.getUserObject() instanceof FileInfo)) return;
   FileInfo nextFile = (FileInfo) node.getUserObject();
   if (node.isLeaf())
   {
      save();
      load(nextFile);
      editor.setCaretPosition(0);
   }
   else
   {
      int pos = editor.getCaretPosition();
      save();
      editor.setCaretPosition(pos);
      editor.requestFocusInWindow();
   }
}

void myDoubleClick (int selRow, TreePath selPath)
{
// if (currentFile.name().equals(selPath.getLastPathComponent())) {
// OsUtl.trace("relaod");
// load(currentFile);
// }
}

// public void valueChanged(TreeSelectionEvent e) {
//
// DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
// .getLastSelectedPathComponent();
//
// if (node == null)
// return;
//
// FileInfo nextFile = (FileInfo) node.getUserObject();
//
// if (node.isLeaf()) {
// save();
// load(nextFile);
// } else {
// save();
// }
// }
//	
private void load (FileInfo nextFile)
{
   doc = new ScriptDocument(this);
   editor.setDocument(doc);
   LineReader r = new LineReader((File) nextFile);
   if (!r.open()) { throw new Failure("Can't read script: " + nextFile.getAbsolutePath()); }
   int pos = 0;
   while (r.hasLine())
   {
      String content = r.nextLine();
      doc.insertLine(pos, content + "\n");
      pos = doc.getLength();
   }
   doc.setDirty(false);
   currentFile = nextFile;
}

public synchronized void save ()
{
   save(false);
}

public synchronized void save (boolean always)
{
   if (currentFile == null) return;
//   OsUtl.trace("Begin saving (" + currentFile.getAbsolutePath() + ")");
   if (always || doc.isDirty())
   {
      int signs = doc.getLength();
      try
      {
         String text = doc.getText(0, signs);
         text = FormatterUtl.removeWhitespaceTail(text);
//         OsUtl.trace("Storing (" + currentFile.getAbsolutePath() + ")");
         FileUtl.writeBytes(currentFile.getAbsolutePath(), text);
      }
      catch (BadLocationException e)
      {
         e.printStackTrace();
         throw new Failure("Can't save content, file " + currentFile);
      }
   }
   // else OsUtl.trace(currentFile + " is not dirty.");
//   currentFile = null;
}

public void find ()
{
   searchText = (String) JOptionPane.showInputDialog(editor, "Enter text", "Find", JOptionPane.PLAIN_MESSAGE, null, null, searchText);
   if (!Empty.is(searchText))
   {
      findPosition = 0;
      findNext();
   }
   editor.requestFocus();
}

public void findNext ()
{
   String text = "";
   try
   {
      text = doc.getText(0, doc.getLength());
   }
   catch (BadLocationException e)
   {
      SysUtl.trace("Invalid location.");
   }
   findPosition = text.indexOf(searchText, findPosition == -1 ? 0 : findPosition);
   if (findPosition != -1)
   {
      setCaretPosition(findPosition);
      findPosition += searchText.length();
   }
}

public void setCaretPosition (int pos)
{
   editor.setCaretPosition(pos);
}

public void reformat () throws BadLocationException
{
   int caretPosition = editor.getCaretPosition();
   int signs = doc.getLength();
   String text = doc.getText(0, signs);
   doc.remove(0, signs);
   doc.formatLines(text, signs);
   setCaretPosition(caretPosition);
}
}
