package ch.wlkl.shell;
import static ch.wlkl.shell.EnvMan.envMan;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.*;
public class Win extends Top {

	public void print () {
		System.out.println("hier bin ich " + getClass());		
	}
	
	public void swtMain () {
	      Display display = new Display ();
	      Shell shell = new Shell (display);
	      say("shell.size " + shell.getSize());
	      final Composite comp = new Composite (shell, SWT.NO_RADIO_GROUP);
	      comp.setBounds(shell.getClientArea());
	      say("comp.size " + comp.getSize());
	      Label label = new Label (comp, SWT.CENTER);
	      label.setText ("Hello_world");
	      final Label lab2 = new Label (comp, SWT.LEFT);
	      lab2.setText ("anfangs text");
	      final Text tx = new Text (comp, SWT.LEFT ); //+ SWT.MULTI);
	      tx.setText ("und dies ist ein text...\nmit einer zweiten Zeile");
	      tx.addModifyListener(new ModifyListener() {
	    	  public void modifyText(ModifyEvent ev) {
	    		  System.out.println("modifyText event " + ev);
	    		  System.out.println("modifyText source " + ev.getSource());
	    		  System.out.println("new Text " + ((Text) ev.getSource()).getText());
	    		  lab2.setText("new text = " + tx.getText());
	    	      comp.pack();
//	    	      comp.redraw();
	    	  }});
	      comp.setLayout(new RowLayout(SWT.VERTICAL));
	      comp.layout(true);
//	      comp.pack();
	      shell.open ();
	      say("lab2.size " + lab2.getSize());
	      while (!shell.isDisposed ()) {
	         if (!display.readAndDispatch ()) display.sleep ();
	      }
	      display.dispose ();
	}

	public void swtMain2 () {
	      final Display display = new Display ();
	      final Shell shell = new Shell (display);
	      say("shell.size " + shell.getSize());
	      final Composite comp = new Composite (shell, SWT.NO_RADIO_GROUP);
	      comp.setBounds(shell.getClientArea());
	      say("comp.size " + comp.getSize());
	      Label label = new Label (comp, SWT.CENTER);
	      label.setText ("Hello_world");
	      label.setSize(120, 30);
	      label.setLocation(20, 20);
	      final Label lab2 = new Label (comp, SWT.LEFT);
	      lab2.setText ("anfangs text");
	      lab2.setSize(620, 29);
	      lab2.setLocation(150, 20);
	      final Text tx = new Text (comp, SWT.LEFT + SWT.MULTI);
	      tx.setText ("und dies ist ein text...\nmit einer zweiten Zeile");
	      tx.setSize(300, 300);
	      tx.setLocation(20, 60);
	      tx.addModifyListener(new ModifyListener() {
	    	  public void modifyText(ModifyEvent ev) {
//	    		  System.out.println("modifyText event " + ev);
//	    		  System.out.println("modifyText source " + ev.getSource());
//	    		  System.out.println("new Text " + ((Text) ev.getSource()).getText());
	    		  int p = tx.getCaretPosition();
	    		  String t = tx.getText();
	    		  String x = t.substring(p < 10 ? 0 : p - 10, p) + "###" + (t.length() > p + 10 ? t.substring(p, p+10) : t.substring(p));
	    		  lab2.setText("arround carret = " + x);
	    	  }
	      });
	      final Button bu = new Button(comp, SWT.PUSH);
	      bu.setText("selectionText state");
	      bu.setLocation(350, 60);
	      bu.setSize(350, 20);
	      bu.addSelectionListener(new SelectionListener() {

	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    		  bu.setText("default selected point " + tx.getSelection() + " count " + tx.getSelectionCount() + " text " + tx.getSelectionText());
	    	  }

	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  bu.setText("selected point " + tx.getSelection() + " count " + tx.getSelectionCount() + " text " + tx.getSelectionText());
	    	  }
	      } );
	      final Button b2 = new Button(comp, SWT.PUSH);
	      b2.setText("home ?");
	      b2.setLocation(350, 80);
	      b2.setSize(350, 20);
	      b2.addSelectionListener(new SelectionListener() {

	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    	  }

	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  b2.setText("home = " + new File(".").getAbsolutePath());
	    	  }
	      } );
	      final Button bOpen = new Button(comp, SWT.PUSH);
	      bOpen.setText("open");
	      bOpen.setLocation(350, 100);
	      bOpen.setSize(40, 20);
	      bOpen.addSelectionListener(new SelectionListener() {
	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    	  }
	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  System.out.println("open pushed");
	    		  MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
	    		  mb.setText("Willst Du ein neues File öffnen und aktuellen Inhalt überschreiben?");
	    		  if (mb.open() != SWT.OK)
	    			  return;
	    		  String fName = new FileDialog(shell, SWT.SAVE).open();
	    		  if (fName == null)
	    			  return;
	    		  File f = new File(fName);
	    		  if (! (f.exists() && f.isFile())) {
	    			  mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
	    			  mb.setText(f.getAbsolutePath() + " existiert nicht, oder ist kein File");
	    			  mb.open();	
	    			  return;
	    		  }
	    		  BufferedReader r = null;
	    		  try {
	    			  r = new BufferedReader(new FileReader(f));
	    		  } catch (FileNotFoundException e) {
	    		  }
	    		  String src = "", s1;
	    		  try {
	    			  while (null != (s1 = r.readLine()))
	    				  src += s1 + "\n";
	    		  } catch (IOException e) {
	    			  fail(e.toString());
	    		  }
	    		  tx.setText(src);

	    	  }
	      });
	      final Button bSave = new Button(comp, SWT.PUSH);
	      bSave.setText("save");
	      bSave.setLocation(400, 100);
	      bSave.setSize(40, 20);
	      bSave.addSelectionListener(new SelectionListener() {

	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    	  }

	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  System.out.println("save pushed");
	    	      FileDialog fiDi = new FileDialog(shell, SWT.SAVE);
	    	      fiDi.setText("Walter's FileDialog style " + fiDi.getStyle());
	    		  System.out.println("SWT.SAVE " + SWT.SAVE + ", 1<<13 " + (1<<13));
	    		  System.out.println("SWT.OPEN " + SWT.OPEN + ", 1<<15 " + (1<<15));
	    	      fiDi.setFilterPath("./eins.txt");
	    	      String nm = fiDi.open ();
	    		  System.out.println("selected " + nm + ", file " + fiDi.getFileName() + " style " + fiDi.getStyle());

	    	  }
	      } );

//	      comp.setLayout(new RowLayout(SWT.VERTICAL));
//	      comp.layout(true);
////	      comp.pack();
	      shell.open ();
	      while (!shell.isDisposed ()) {
	         if (!display.readAndDispatch ()) display.sleep ();
	      }
	      display.dispose ();
	}
	boolean srcModified = false;
	Display display = null;
    Shell shell = null;
	TextIO src = null;
	Button srcOp = null;
	Button srcSv = null;
	Button srcAs = null;
	Button runSh = null;
	Button runDa = null;
	Label outLb = null;
	TextIO out = null;
	Button outAs = null;
   
    public void adapt () {
	      srcSv.setEnabled(src.isModified && src.file != null);
    }

    public void new3 () {
    	display = new Display();
//    	say("display " + display.getBounds());
    	shell = new Shell (display);
    	shell.setText("Walter's Java Shell");
//    	say("shell " + shell.getBounds());
    	src = new TextIO(shell);
    	srcOp = new Button(shell, SWT.PUSH);
    	srcOp.setText("open");
    	srcSv = new Button(shell, SWT.PUSH);
    	srcSv.setText("save");
    	srcAs = new Button(shell, SWT.PUSH);
    	srcAs.setText("save as");
    	runSh = new Button(shell, SWT.PUSH);
    	runSh.setText("shell");
    	runDa = new Button(shell, SWT.PUSH);
    	runDa.setText("data");
	    outLb = new Label(shell, SWT.SHADOW_IN + SWT.LEFT);
	    out = new TextIO(shell);
    	outAs = new Button(shell, SWT.PUSH);
    	outAs.setText("save as");
    }
    
    public int max(int i, int j) {
    	return i > j ? i : j;
    }
    
    public void layout3(int w, int h) {
     	int x1 = 5;
    	int y1 = 5;     	
    	int w1 = 50;
    	int x2 = 2 * x1 + w1;
    	int w2 = max(w - x2 - x1, 100);
    	int h0 = 20;
    	int h1 = max((h - h0 - 4 * y1) / 2, 5 * h0 + 4 * y1);
    	int y2 = x1 * 3 + h0 + h1;
    	src.text.setBounds(x2, y1, w2, h1);
    	srcOp.setBounds(x1, y1, w1, h0);
    	srcSv.setBounds(x1, y1+      (y1+h0), w1, h0);
    	srcAs.setBounds(x1, y1 + 2 * (y1+h0), w1, h0);
    	runSh.setBounds(x1, y2  -  (y1+h0), w1, h0);
    	outLb.setBounds(x2, y2-y1-h0, w2, h0);
	    out.text.setBounds(x2, y2, w2 ,h1);
	   	runDa.setBounds(x1, y2, w1, h0);
    	outAs.setBounds(x1, h-y1-h0, w1, h0);
    }
    
    public void swtMain3 () {
	      new3();
//	      layout3(shell.getClientArea().width, shell.getClientArea().height);
	      shell.addControlListener(new ControlListener() {

			public void controlMoved(ControlEvent arg0) {
				// say("shell moved to " + shell.getLocation());				
			}

			public void controlResized(ControlEvent arg0) {
				// say("shell resized to " + shell.getClientArea());
				layout3(shell.getClientArea().width, shell.getClientArea().height);				
			}});
	      srcOp.addSelectionListener(new SelectionListener() {
	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    	  }
	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  src.open();
	    	  }
	      });
	      srcSv.addSelectionListener(new SelectionListener() {
	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    	  }
	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  src.save(src.file);
	    	  }
	      });
	      srcAs.addSelectionListener(new SelectionListener() {
	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    	  }
	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  src.save();
	    	  }
	      });
	      outAs.addSelectionListener(new SelectionListener() {
	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    	  }
	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  out.save();
	    	  }
	      });
	      runSh.addSelectionListener(new SelectionListener() {
	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    	  }
	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  compRun('s');
	    	  }
	      });
	      runDa.addSelectionListener(new SelectionListener() {
	    	  public void widgetDefaultSelected(SelectionEvent arg0) {
	    	  }
	    	  public void widgetSelected(SelectionEvent arg0) {
	    		  compRun('d');
	    	  }
	      });
	      adapt();
	      shell.open ();
	      while (!shell.isDisposed ()) {
	    	  if (!display.readAndDispatch ()) display.sleep ();
	      }
	      display.dispose ();
	}

	public void compRun(char type) {
		String s = src.text.getText();
		PrintStream oldOut = System.out;
		PrintStream oldErr = System.err;
		String tyNa = type == 's' ? "shell" : type == 'd' ? "data" : "type " + type;
		Write<String> bb = new WriteOut();
		PrintStream newOut = new PrintStream(new OutputStream2Write(bb));
		out.text.setText("");
		bb.open("w");
		outLb.setText("compiling " + tyNa);
		envMan().push(new Env<String, String>(">£", bb));
		System.setOut(newOut);
		System.setErr(newOut);
		s = s == null ? "" : s;
		Class<? extends Run> cl = new Compiler(EnvMan.envMan().loader(), new Buf<String>(s)).compileClassCatch(type, null);
		if (cl != null) {
			outLb.setText("running " + tyNa + " " + cl);
			try {
				cl.newInstance().run();
			} catch (Throwable e) {
				bb.write("catched Throwable" + e);
				Throwable c = e;
				while (null != (c = c.getCause()))
					bb.write("  caused by " + c);
				e.printStackTrace();
			} 
		}
		envMan().pop();
		System.setOut(oldOut);
		System.setErr(oldErr);
//		r.run();
	}
	
	class TextIO {
		Text text;
		boolean isModified = false;
		File file = null;
		TextIO(Shell shell) {
			text = new Text (shell, SWT.LEFT + SWT.MULTI);
			text.addModifyListener(new ModifyListener () {
				public void modifyText(ModifyEvent arg0) {
					isModified = true;
					adapt();				
				}});
		}

		public void open() {
			if (isModified) {
				MessageBox mb = new MessageBox(text.getShell(), SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
				mb.setText("Willst Du ein neues File öffnen und aktuellen Inhalt überschreiben?");
				if (mb.open() != SWT.OK)
					return;
			}
			String fName = new FileDialog(text.getShell(), SWT.OPEN).open();
			if (fName == null)
				return;
			File f = new File(fName);
			if (! (f.exists() && f.isFile())) {
				MessageBox mb = new MessageBox(text.getShell(), SWT.ICON_ERROR | SWT.OK);
				mb.setText(f.getAbsolutePath() + " existiert nicht, oder ist kein File");
				mb.open();	
				return;
			}
			open(f);
		}

		public void open(File f) {
			BufferedReader r = null;
			try {
				r = new BufferedReader(new FileReader(f));
			} catch (FileNotFoundException e) {
				fail("cannot read file " + f.getAbsolutePath() + " exception " + e);
			}
			String src = "", s1;
			try {
				while (null != (s1 = r.readLine()))
					src += s1 + "\n";
				r.close();
			} catch (IOException e) {
				fail("read error on " + f.getAbsolutePath() + " exception " + e.toString());
			}
			text.setText(src);
			isModified = false;
			file = f;
			adapt();
		}
		public void save() {
			String fName = new FileDialog(text.getShell(), SWT.SAVE).open();
			if (fName == null)
				return;
			File f = new File(fName);
			if (f.exists()) {
				MessageBox mb = new MessageBox(text.getShell(), SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
				mb.setText("das bestehende File " + f.getAbsolutePath() + " überschrieben?");
				if (mb.open() != SWT.OK)
					return;
			}
			save(f);
		}

		public void save(File f) {
			FileWriter w = null;
			try {
				w = new FileWriter(f);
				w.write(text.getText());
				w.close();
			} catch (IOException e) {
				fail("write error on file " + f.getAbsolutePath() + " exception " + e);
			}
			isModified = false;
			file = f;
			adapt();
		}
	}
	
	class WriteOut implements Write<String> {

		public void write(String arg) {
			out.text.setText(out.text.getText() + Ut.crLf(arg) + "\r\n");			
		}

		public void close() {
		}

		public void open(String opt) {
		}

		public void reset(Object... args) {
			// TODO Auto-generated method stub
			
		}
		
	}
	public static void main (String ... args) {
		Win win = new Win();
		win.print();
		win.swtMain3();
	}
}

