package brn.gui.editors;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import jplot.Arguments;
import jplot.DrawPlot;
import jplot.State;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;

import brn.gui.Activator;
import brn.gui.datasource.Source;
import brn.sim.data.XplotData;

public class XPlotEditor extends EditorPart implements IPropertyChangeListener {

	public static final String ID = "brn.gui.editors.XPlotEditor";
  private static final int REFRESH_DELAY = 1000 /* ms */;
  private RefreshTimer timer;  //  @jve:decl-index=0:
  private boolean secondTry;

  private XplotData data;
  private Composite top = null;
  private DrawPlot pane;
  private Arguments args;

  public XPlotEditor() {
		super();
    this.secondTry = false;

    timer = new RefreshTimer();
	}

  public boolean isRefresh() {
    return timer.isRunning();
  }

  public void refresh(boolean refresh) {
    if (refresh) {
      try {
        secondTry = false;
        refresh();
      } catch (CoreException e) {
        Activator.log(e);
        timer.stop();
        return;
      }

      timer.start();
    }
    else
      timer.stop();
  }

  public void resetZoom() {
    pane.getPl().setViewNo(0);
    pane.repaint();
  }

//  public void openTree() {
//    JClassTree ct = new JClassTree();
//    ct.setModal(false);
//    ct.setJPane(pane);
//    ct.show();
//  }


  @Override
  public void init(IEditorSite site, IEditorInput input) throws PartInitException {
    setSite(site);
    setInput(input);

    SimulatorItemInput dataInput = (SimulatorItemInput) getEditorInput();
    if (null == dataInput
        || null == dataInput.getSimulator()
        || !dataInput.getSimulator().isConnected())
      throw new PartInitException("Simulator in error state.");

    dataInput.getSimulator().addPropertyChangeListener(this);
    try {
      data = (XplotData) dataInput.getSimulator().getContribution(dataInput.getId());
    } catch (CoreException e) {
      throw new PartInitException(e.getStatus());
    }
  }

  /**
   * Closes the editor programmatically.
   */
  public void close() {
    Display display = getSite().getShell().getDisplay();
    display.asyncExec(new Runnable() {
            public void run() {
                getSite().getPage().closeEditor(XPlotEditor.this, false);
            }
        });
  }

  @Override
  public void dispose() {
    if (null != timer)
      timer.stop();

    SimulatorItemInput input = (SimulatorItemInput) getEditorInput();
    if (null != input.getSimulator())
      input.getSimulator().removePropertyChangeListener(this);

    super.dispose();
  }

  @Override
  public void createPartControl(Composite parent) {
    String path = "";
    for (int i = 0; i < data.getPath().length; i++)
      path += data.getPath()[i] + ", ";

    setPartName(path);
    top = new Composite(parent, SWT.EMBEDDED);

    try {
      args = new Arguments();
      pane = new DrawPlot(args, data.getContent());
      java.awt.Frame locationFrame = SWT_AWT.new_Frame(this.top);
      locationFrame.add(this.pane);
    } catch (Exception e) {
      e.printStackTrace();
      return;
    }

    timer.start();
  }

  public class RefreshTimer implements Runnable {
    private boolean stop = false;
    public void run() {
      try {
        refresh();
      } catch (CoreException e) {
        Activator.log(e);
        stop = true;
        return;
      }
      if (!stop)
        start();
    }
    public void start() {
      this.stop = false;
      getEditorSite().getShell().getDisplay().timerExec(REFRESH_DELAY, timer);
    }
    public void stop() {
      this.stop = true;
    }
    public boolean isRunning() {
      return !stop;
    }
  }

  protected void refresh() throws CoreException {
    if (!getEditorSite().getPage().isPartVisible(getSite().getPart()))
      return;

    SimulatorItemInput input = (SimulatorItemInput) getEditorInput();

    if (!input.getSimulator().isConnected())
      return;

    if (input.getSimulator().isPaused()) {
      if (secondTry) {
        // XXX pane is redrawn here because otherwise zooming wont work properly...
        pane.repaint();
        return;
      }
      secondTry = true;
    } else
      secondTry = false;

    data = (XplotData) input.getSimulator().getContribution(input.getId());
    pane.repaint();
  }

  @Override
  public void setFocus() {
    top.setFocus();
  }

  @Override
  public boolean isDirty() {
    return false;
  }

  @Override
  public boolean isSaveAsAllowed() {
    return false;
  }

  @Override
  public void doSave(IProgressMonitor monitor) {
  }

  @Override
  public void doSaveAs() {
  }

  public void propertyChange(PropertyChangeEvent event) {
    if (event.getProperty().equals(Source.CONNECTED)
      ||event.getProperty().equals(Source.DATASOURCE_DISPOSED)) {
      SimulatorItemInput input = (SimulatorItemInput) getEditorInput();
      if (null == input.getSimulator()
          ||!input.getSimulator().isConnected()) {
        if (null != input.getSimulator())
          input.getSimulator().removePropertyChangeListener(this);
        close();
      }
    }
  }

  public void saveText() {
    Shell shell = getSite().getShell();
    FileDialog dialog = new FileDialog(shell, SWT.SAVE);
    dialog.setFilterNames (new String [] {"XPlot Files", "All Files (*.*)"});
    dialog.setFilterExtensions (new String [] {"*.xpl", "*.*"}); //Windows wild cards

    String fileName = dialog.open();
    if (null == dialog.getFileName() || dialog.getFileName().length() == 0)
      return;

    if (!fileName.endsWith(".xpl"))
      fileName += ".xpl";

    BufferedWriter writer;
    try {
      writer = new BufferedWriter(new FileWriter(fileName));
      writer.write(this.data.getContent());
      writer.close();
    } catch (IOException e) {
      e.printStackTrace();
      MessageBox errorDlg = new MessageBox(shell, SWT.OK);
      errorDlg.setText("Error");
      errorDlg.setMessage(e.getMessage());
      errorDlg.open();
    }
  }

  public void saveImage() {
    Shell shell = getSite().getShell();
    FileDialog dialog = new FileDialog(shell, SWT.SAVE);
    dialog.setFilterNames (new String [] {"Text Files", "All Files (*.*)"});
    dialog.setFilterExtensions (new String [] {"*.png", "*.*"}); //Windows wild cards

    String fileName = dialog.open();
    if (null == dialog.getFileName() || dialog.getFileName().length() == 0)
      return;

    if (!fileName.endsWith(".png"))
      fileName += ".png";
    
//    if(fc.getFileFilter().equals(pngFilter)) {
//      if(fileName.endsWith(".png") == false)
//        fileName = fileName.concat(".png");
      pane.getPl().setState(State.PRINTING);
      pane.emitPng(pane.openPngFile(fileName), pane.getCanvas());
      pane.getPl().setState(State.NORMAL);
//      }
//    else if(fc.getFileFilter().equals(a4psFilter))
//      {
//   if(fileName.endsWith(".a4.ps") == false)
//     fileName = fileName.concat(".a4.ps");
//   mainPanel.getPl().state = State.PRINTING;
//   mainPanel.emitPS(mainPanel.openPSFile(fileName), mainPanel.getPl().state);
//   mainPanel.getPl().state = State.NORMAL;
//      }
//    else if(fc.getFileFilter().equals(tex3psFilter))
//      {
//   if(fileName.endsWith(".tex3.ps") == false)
//     fileName = fileName.concat(".tex3.ps");
//   mainPanel.getPl().state = State.FIGING;
//   mainPanel.emitPS(mainPanel.openPSFile(fileName), mainPanel.getPl().state);
//   mainPanel.getPl().state = State.NORMAL;
//    }
//    else if(fc.getFileFilter().equals(lvspsFilter))
//      {
//   if(fileName.endsWith(".lvs.ps") == false)
//     fileName = fileName.concat(".lvs.ps");
//   mainPanel.getPl().state = State.THINFIGING;
//   mainPanel.emitPS(mainPanel.openPSFile(fileName), mainPanel.getPl().state);
//   mainPanel.getPl().state = State.NORMAL;
//      }
//    else
//      System.out.println("jPlot: unknown file type specified while saving, file NOT saved");

//
//
//    try {
//      saveImage(fileName);
//    } catch (Exception e) {
//      e.printStackTrace();
//      MessageBox errorDlg = new MessageBox(shell, SWT.OK);
//      errorDlg.setText("Error");
//      errorDlg.setMessage(e.getMessage());
//      errorDlg.open();
//    }
  }

//  /**
//   * Saves the diagram into the specified file
//   *
//   * @param sFileName
//   * @throws JimiException
//   */
//  public void saveImage(String sFileName) throws Exception {
//    Dimension dim = new Dimension(1400, 1050);
//    boolean visible = getSite().getPage().isEditorAreaVisible();
//    if (!visible) {
//      pane.setSize(dim.width, dim.height);
//      pane.validate();
//    }
//
//    Dimension d = pane.getSize();
//    BufferedImage img = new BufferedImage(d.width, d.height,
//            BufferedImage.TYPE_INT_RGB);
//    pane.draw(img.createGraphics(), d.width, d.height);
//    Jimi.putImage(img, sFileName);
//
//    if (!visible) {
//      dispose();
//    }
//  }

//
//  public static void saveImage(JistAdapter adapter, int dataId, String sFileName)
//      throws Exception {
//    Dimension dim = new Dimension(1400, 1050);
//    JPlotLayout pane = createPane(adapter, dataId);
//    pane.setVisible(true);
//    pane.setSize(dim.width, dim.height);
////  pane.setBatch(false);
////    pane.setDoubleBuffered(false);
//
//    Dimension d = pane.getSize();
//    BufferedImage img = new BufferedImage(d.width, d.height,
//            BufferedImage.TYPE_INT_RGB);
//    pane.draw(img.createGraphics(), d.width, d.height);
//    Jimi.putImage(img, sFileName);
//  }

//  public void dataPrint() {
//    Color saveColor;
//    if (null == pageFormat)
//      pageFormat = PrinterJob.getPrinterJob().defaultPage();
//
//    PrinterJob printJob = PrinterJob.getPrinterJob();
//    printJob.setPrintable(pane, pageFormat);
//    printJob.setJobName("Grid Demo");
//    if (printJob.printDialog()) {
//      try {
//        saveColor = pane.getBackground();
//        if (!saveColor.equals(Color.white)) {
//          pane.setBackground(Color.white);
//        }
//        pane.setPageAlign(AbstractPane.TOP, AbstractPane.CENTER);
//        RepaintManager currentManager = RepaintManager.currentManager(pane);
//        currentManager.setDoubleBufferingEnabled(false);
//        printJob.print();
//        currentManager.setDoubleBufferingEnabled(true);
//        pane.setBackground(saveColor);
//      } catch (PrinterException pe) {
//        System.out.println("Error printing: " + pe);
//      }
//    }
//  }
//
//  public void dataLayout() {
//    if (null == pageFormat)
//      pageFormat = PrinterJob.getPrinterJob().defaultPage();
//
//    PrinterJob pj = PrinterJob.getPrinterJob();
//    pageFormat = pj.pageDialog(pageFormat);
//  }

}
