import java.awt.*;
import java.io.*;
import java.util.*;
import java.awt.event.*;

/**
* TextHandler, handles the window of the selected file
* at the moment uses a TextArea to handle all the text
* commands.
*/
public class TextHandler extends Frame implements WindowListener,  KeyListener {
	private JPETextArea textArea;
	public OpenFile file;
	JPE jpe;

	/**
	* create the Texthandler, it doesn't open the window at
	* this stage.
	*/
	public TextHandler(MenuBar bar,JPE jpe) {
		textArea = new JPETextArea(jpe);
		setMenuBar(bar);
		this.jpe=jpe;
		setTitle();
		textArea.addKeyListener(this);
		add("Center", textArea);
		addWindowListener(this);
	}

	/**
	* init the Text/Edit window, looks in the xml setup
	* for its screensize and fontsize
	*/
	public void init() {

		// get the defined machine ( from config.xml )
		String setup=jpe.getProperty("setup","machine");
		
		// if no defined machine was found default to netbook
		if (setup==null) this.setSize(640, 480);

		// figure out the used machine		
		if (setup.equals("netbook") ) {
			// setup to netbook requested
  			this.setSize(640, 480);
		} else if (setup.equals("psion7") ) {
			// setup to psion7 requested
			this.setSize(640, 480);
		} else if (setup.equals("5mx")) {
			// setup to 5mx requested
			this.setSize(640, 240);
		} else if (setup.equals("revo")) {
			// setup to revo requested
			this.setSize(480, 160);
		} else {
			// if unknown machine defined also default to netbook
			this.setSize(640, 480);
		} 

		// open and make this window visible		
		this.setVisible(true);  

		// get the defined fontsize ( from config.xml )
		String fontsize=jpe.getProperty("setup","fontsize");

		// if no fontsize is defined default to 15	
		if (setup==null) setFontSize(15);

		// try to parse the defined fontsize
		try {
			// set the defined fontsize
			setFontSize(Integer.parseInt(fontsize));
		} catch(Exception e) {
			// if something goes wrong default to 15
			setFontSize(15);
		}

		// get the defined machine ( from config.xml )
		String fontname=jpe.getProperty("setup","fontname");
		if (fontname!=null) {
			if (fontname.equals("Arial")) {
				setNewFont("Arial");				
			} else if (fontname.equals("Times")) {
				setNewFont("Times New Roman");				
			} else if (fontname.equals("Courier")) {
				setNewFont("Courier");				
			}
		}
	}


	/**
	* set the window to a new size and make it visible at this size
	*/
	public void setWindowSize(int sizex, int sizey) {
		this.setSize(sizex,sizey);
		this.setVisible(true);
	}
	
	/**
	* set default text to the title bar
	*/
	private void setTitle() {
		if (file==null) {
			setTitle("No file Selected ");
		} else {
			setTitle("File : "+file.getName());
		}
	}
	

	/**
	* increase the fontsize (zoom) with 1
	*/
	public int doFontUp() {
		// get current selected font
		Font curf=textArea.getFont();

		// get the name of this font
		String name=curf.getName();

		// get the size of this font
		int size=curf.getSize();

		// create a new font based on the old one but bigger
		Font newf=new Font(name,Font.PLAIN,size+1);

		// set this new font into the textArea		
		textArea.setFont(newf);

		// return the new size
		return(size+1);
	}

	/**
	* set the fontsize of the textArea to new size
	*/
	public void setFontSize(int size) {
		// get the current selected font
		Font curf=textArea.getFont();

		// get the name of this font
		String name=curf.getName();

		// create a new font based on the old one with new size
		Font newf=new Font(name,Font.PLAIN,size);

		// set this new font into the textArea
		textArea.setFont(newf);
	}


	/**
	* decrease the fontsize (zoom) with 1
	*/
	public int doFontDown() {
		// get the current selected font
		Font curf=textArea.getFont();

		// get the name of this font
		String name=curf.getName();

		// get the size of the font
		int size=curf.getSize();

		// create a new font based on the old one but smaller
		Font newf=new Font(name,Font.PLAIN,size-1);

		// set this new font into the textArea
		textArea.setFont(newf);

		// return the new size of the current font
		return(size-1);
	}

	/**
	* decrease the fontsize (zoom) with 1
	*/
	public void setNewFont(String name) {
		// get the current selected font
		Font curf=textArea.getFont();

		// get the size of the font
		int size=curf.getSize();

		// create a new font based on the old one but smaller
		Font newf=new Font(name,Font.PLAIN,size);

		// set this new font into the textArea
		textArea.setFont(newf);
	}
	


	public void keyPressed(KeyEvent e) {
			jpe.say();
	}

	public int gotoLine(int linenumber) {
		// need a smart way to do this
		String body=textArea.getText();
		int lastpos=1;
		int line=1;
		if (linenumber<2) {
			// lets be smart and do this direct
			textArea.setCaretPosition(1);
			return(1);
		}

		int pos=body.indexOf("\n",lastpos);
		while (pos!=-1 && line!=(linenumber-1)) {
			line=line+1;
			lastpos=pos+1;
			pos=body.indexOf("\n",lastpos);
		} 
		if (line==linenumber-1) {
			textArea.setCaretPosition(pos+1);
			return(line+1);
		} else {
			textArea.setCaretPosition(body.length()-2);
			return(line);
		}
	}

	public boolean gotoLineWith(String key) {
		// need a smart way to do this
		String body=textArea.getText();
		int pos=body.indexOf(key);
		if (pos!=-1) {
			textArea.setCaretPosition(pos);
			return(true);
		} else {
			return(false);
		}
	}

	public boolean gotoLineWith(String key,int startpos) {
		// need a smart way to do this
		String body=textArea.getText();
		int pos=body.indexOf(key,startpos);
		if (pos!=-1) {
			textArea.setCaretPosition(pos);
			return(true);
		} else {
			return(false);
		}
	}

	/**
	* Finds next occurence of key1 and/or key2 from the current
	* cursor position or from given pos, and returns the postition
	* of key1 or key2, the one closest to the start position.
	* Returns -1 when nothing was found.
	* Both key1 and key2 may be null in which case nothing is
	* searched for that key.
	*/
	private int findNext( String key1, String key2, int pos ) {
		String body=textArea.getText();
		int startPos = (pos >= 0) ? pos : textArea.getCaretPosition() + 1;
		int pos1 = (key1==null) ? -1 : body.indexOf( key1, startPos );
		int pos2 = (key2==null) ? -1 : body.indexOf( key2, startPos );
		if ( pos1 < 0 && pos2 < 0 ) { 
			return (-1);
		} else if ( pos1 < 0 ) {
			return pos2;
		} else if ( pos2 < 0 ) {
			return pos1;
		} else { 
			return ((pos1<pos2) ? pos1 : pos2);
		}	
	}		

	
	/**
	* Finds previous occurence of key1 and/or key2 from the current
	* cursor position or from given pos, and returns the postition
	* of key1 or key2, the one closest to the start position.
	* Returns -1 when nothing was found.
	* Both key1 and key2 may be null in which case nothing is
	* searched for that key.
	*/
	private int findPrev( String key1, String key2, int pos) {
		String body=textArea.getText();
		int startPos = (pos >= 0) ? pos : textArea.getCaretPosition() - 1;
		int pos1 = (key1==null) ? -1 : body.lastIndexOf( key1, startPos );
		int pos2 = (key2==null) ? -1 : body.lastIndexOf( key2, startPos );
		System.out.println("pos1 " + pos1 + " pos2 " + pos2 );
		if ( pos1 < 0 && pos2 < 0 ) { 
			return (-1);
		} else if ( pos1 < 0 ) {
			return pos2;
		} else if ( pos2 < 0 ) {
			return pos1;
		} else { 
			return ((pos1>pos2) ? pos1 : pos2);
		}	
	}		


	/**
	* Finds next method in current file. The start of a method is
	* recognized as a line that has the string "public " or "private "
	* followed by a "(" and a "{" character somewhere on that same line.
	*/
	public boolean gotoNextMethod() {
		int pos1 = -1;
		while ( true ) {
			pos1 = findNext( "public ", "private ", pos1 );
			int line1 = posToLine( pos1 );
			int line2 = posToLine(findNext("(", null, pos1));
			int line3 = posToLine(findNext("{", null, pos1));
			if ( line1 >= 0 && line1 == line2 && line2 == line3 ) {
				textArea.setCaretPosition( pos1 );
				return (true);
			} else if ( pos1 < 0 ) {
				return (false);
			}
			pos1++;
		}		
	}

	/**
	* Finds prev method in current file. The start of a method is
	* recognized as a line that has the string "public " or "private "
	* followed by a "(" and a "{" character somewhere on that same line.
	*/
	public boolean gotoPrevMethod() {
		int pos1 = -1;
		while ( true ) {
			pos1 = findPrev( "public ", "private ", pos1 );
			int line1 = posToLine( pos1 );
			int line2 = posToLine(findNext("(", null, pos1));
			int line3 = posToLine(findNext("{", null, pos1));
			if ( line1 >= 0 && line1 == line2 && line2 == line3 ) {
				textArea.setCaretPosition( pos1 );
				return (true);
			} else if ( pos1 < 0 ) {
				return (false);
			}
			pos1--;
		}		
	}



	public void useFile(OpenFile file) {
		if (this.file!=null) {
			this.file.setCaretPosition(textArea.getCaretPosition());
			this.file.setText(textArea.getText());
		}
		this.file=file;
		jpe.setCompileState(file.isCompiled());
		jpe.setSaveState(!file.isDirty());
		jpe.setLockState(file.isLocked());
		textArea.setEditable(!file.isLocked());
		textArea.setText(file.getText());
		textArea.setCaretPosition(file.getCaretPosition());
		jpe.say();
		repaint();
		if (!file.getName().equals("StdOut") && !file.getName().equals("StdErr")) {
			jpe.putProperty("setup","selectedfile",file.getName());
		}
	}


	public OpenFile getEditFile() {
		if (file!=null) {
			file.setText(textArea.getText());
		}
		return(file);
	}

	public String getEditFilename() {
		return(file.getName());
	}


	public String getSelectedText() {
		return(textArea.getSelectedText());
	}

	public String cutSelectedText() {
		String text=textArea.getSelectedText();
		textArea.replaceRange("",textArea.getSelectionStart(),textArea.getSelectionEnd());
		return(text);
	}
	
	public void reloadFile() {
		if (file!=null) textArea.setText(file.getText());
	}

	public void insertText(String body) {
		textArea.insert(body,textArea.getCaretPosition());
	}

	public void selectAll() {
		textArea.selectAll();
	}

	public int getCursorPos() {
		return(textArea.getCaretPosition());
	}

	public boolean getAskMode() {
		return(textArea.getAskMode());
	}

	public void setAskMode(AskInterface askCaller,String command,String usermsg,boolean oneshot) {
		textArea.setAskMode(askCaller,command,usermsg,oneshot);
	}


	public int getCursorLine() {
		return ( posToLine(getCursorPos()) );
	}

	/**
	* Returns the number of the line that holds pos.
	*/
	public int posToLine( int pos ) {
		// need a smart way to figure out the line number
		if ( pos < 0 ) {
			return (-1);
		}
		String body=textArea.getText();
		int lastpos=1;
		int line=1;
		int nextPos=body.indexOf("\n",lastpos);
		while (nextPos!=-1 && nextPos<pos) {
			line=line+1;
			lastpos=nextPos+1;
			nextPos=body.indexOf("\n",lastpos);
		}
		return(line);
	}



    public void windowDeiconified(WindowEvent event) {
    }

    public void windowIconified(WindowEvent event) {
    }

    public void windowActivated(WindowEvent event) {
    }

    public void windowDeactivated(WindowEvent event) {
    }

    public void windowOpened(WindowEvent event) {
    }

    public void windowClosed(WindowEvent event) {
    }

    public void windowClosing(WindowEvent event) {
    }

	public void keyTyped(KeyEvent e)	{
		// very bad trick to filter for dirty key needs a fix !
		int val=(int)e.getKeyChar();
		if (val>10 & !file.isLocked()) {
			int kem=e.getModifiers();
			//System.out.println("K="+kem);
			if (kem==0) {
				file.setDirty();
				jpe.setCompileState(file.isCompiled());
			}
		}
		jpe.setSaveState(!file.isDirty());
	}

	public void keyReleased(KeyEvent e) {
		jpe.say();
	}

	public void setEditable(boolean state) {
		textArea.setEditable(state);
	}


}
