package examples.zac.update;

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import weblogic.common.*;
import weblogic.event.actions.*;
import weblogic.event.common.*;
import weblogic.event.evaluators.*;
import weblogic.gui.ExceptionPanel;
import weblogic.zac.*;
import weblogic.jndi.*;
import javax.naming.*;

/**
 * This applet is updateable automatically when its published
 * version changes. It lets the user know when changes occur,
 * and provides a simple interface to update the application
 * and restart.
 *
 * @author                    Copyright (c) 1998-2000 by BEA Systems, Inc.
 *                            All Rights Reserved.
 */
public class UpdateApplet extends Applet implements Runnable,
WindowListener, ActionListener, ActionDef {
  
  void p(String s) {
    System.out.println("UpdateZac: " + s);
  }
  
  private MenuItem zacstat, help, quit;
  private Button flasher;
  
  private boolean updatePending = false, flasherPressed = false;
  
  private Frame frame;
  
  private Frame getFrame() {
    if (frame == null) {
      for (Container cont = getParent(); cont != null; cont = cont.getParent()) {
        if (cont instanceof Frame) {
          frame = (Frame)cont;
          break;
        }
      }
    }
    return frame;
  }
  
  public UpdateApplet() {
  }
  
  /* applet initialization method */
  public void init() {
    setLayout(new GridBagLayout());
    setBackground(Color.lightGray);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.insets = new Insets(5,5,5,5);
    Font f = new Font("SansSerif", Font.BOLD, 10);
    /* Menu bar */
    MenuBar mbar = new MenuBar();
    Menu m = new Menu("ZAC");
    
    m.setFont(f);
    m.add(zacstat = new MenuItem("ZAC Status..."));
    zacstat.addActionListener(this);
    m.add(quit = new MenuItem("Quit"));
    quit.addActionListener(this);
    mbar.add(m);
    
    m = new Menu("Help");
    m.setFont(f);
    m.add(help = new MenuItem("About..."));
    help.addActionListener(this);
    mbar.setHelpMenu(m);
    
    mbar.setFont(f);
    getFrame().setMenuBar(mbar);
    
    gbc.anchor = gbc.CENTER;
    gbc.fill = gbc.NONE;
    gbc.gridx = gbc.gridy = 0;
    gbc.gridwidth = gbc.REMAINDER;
    Label l = null;
    String lbl = getParameter("label");
    if (lbl == null) {
      l = new Label("unlabeled image");
      l.setFont(new Font("SansSerif", Font.ITALIC | Font.BOLD, 18));
    } else {
      l = new Label(lbl);
      l.setFont(new Font("SansSerif", Font.BOLD, 18));
    }
    add(l, gbc);
    getFrame().addWindowListener(this);
    
    gbc.gridy++;
    gbc.anchor = gbc.CENTER;
    lbl = getParameter("image");
    if (lbl == null) lbl = "tricskul.gif";
    add(new ImageCanvas(lbl), gbc);
    
    /* explicit update button */
    gbc.gridy++;
    gbc.gridx = 0;
    gbc.gridwidth = 1;
    gbc.anchor = gbc.EAST;
    gbc.fill = gbc.NONE;//HORIZONTAL;
    gbc.gridx++;
    gbc.anchor = gbc.WEST;
    flasher = new Button("Update Pending");
    flasher.setFont(new Font("SansSerif", Font.ITALIC, 12));
    flasher.setEnabled(false);
    flasher.addActionListener(this);
    add(flasher, gbc);
    
    /* bogus label for spacing */
    gbc.gridy++;
    gbc.gridx = 0;
    l = new Label(" ");
    gbc.fill = gbc.BOTH;
    gbc.gridwidth = gbc.REMAINDER;
    gbc.weightx = gbc.weighty = 1.0;
    add(l, gbc);
    
  }
  
  /* applet start method */
  public void start() {
    new Thread(this, "Applet-Updater").start();
  }
  
  /* ActionDef interface */
  public boolean isLongRunning() {
    return false;
  }
  
  public void setServices(T3ServicesDef sv) {
  }
  public void registerInit(ParamSet p) {
  }
  
  public synchronized void action(EventMessageDef ev) {
    p("update pending");
    updatePending = true;
    notifyAll();
  }
  
  private void loadImageIcon() {
    try {
      java.net.URL u = getClass().getResource("/weblogic/graphics/W.gif");
      Image i = Toolkit.getDefaultToolkit().createImage((java.awt.image.ImageProducer)u.getContent());
      getFrame().setIconImage(i);
    } catch (Error ignore) {
    } catch (Exception ignore) {
    }
  }
  /* Runnable interface */
  
  public synchronized void run() {
    /* look for previous size, if any,
     * in system properties.
     */
    int w = Integer.getInteger("zac.update.width", 400).intValue();
    int h = Integer.getInteger("zac.update.height", 400).intValue();
    getFrame().setSize(w, h);
    /* look for previous screen location, if any,
     * in system properties.
     */
    int x = Integer.getInteger("zac.update.screenX", 30).intValue();
    int y = Integer.getInteger("zac.update.screenY", 30).intValue();
    getFrame().setLocation(new Point(x,y));
    
    loadImageIcon();
    
    try {
      connectToWebLogic();
      Frame f = getFrame();
      if (f != null) {
        f.invalidate();
        f.doLayout();
        f.validate();
        f.doLayout();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    
    while (!updatePending) {
      try {
        wait();
      } catch (InterruptedException e) {}
    }
    
    /* There is now an update pending.  Start flashing
     * the button.
     */
    flasher.setEnabled(true);
    flasher.setFont(new Font("SansSerif", Font.BOLD, 12));
    while (!flasherPressed) {
      flasher.setForeground(Color.red);
      flasher.setLabel(" UPDATE ");
      nap(1000);
      flasher.setForeground(Color.yellow);
      flasher.setLabel(" PENDING ");
      nap(1000);
    }
    
    /* update pending - flash the button */
    flasher.setForeground(Color.black);
    flasher.setEnabled(false);
    flasher.setLabel("Updating...");
    flasher.setFont(new Font("SansSerif", Font.ITALIC, 12));
    
    /* Use the current zac to do updates */
    ZAC zc = ZAC.getCurrentZAC();
    if (zc == null) {
      p("no current ZAC context - was this running from local CLASSPATH?");
      return;
    }
    /* Save previous width, height, X & Y locations
     * in system properties so the new instance can
     * see them.
     */
    Rectangle bounds = getFrame().getBounds();
    Dimension sz = getFrame().getSize();
    Properties pp = System.getProperties();
    pp.put("zac.update.width",
           String.valueOf(sz.width));
    pp.put("zac.update.height",
           String.valueOf(sz.height));
    pp.put("zac.update.screenX",
           String.valueOf(bounds.x));
    pp.put("zac.update.screenY",
           String.valueOf(bounds.y));
    pp.put("zac.update.restart", "true");
    System.setProperties(pp);
    getFrame().setVisible(false);
    getFrame().dispose();
    zc.update();
    try {
      zc.launch();
    } catch (Exception e) {
    }
  }
  
  private void connectToWebLogic() throws Exception {
    
    String t3url = null;
    Enumeration enum = ZACLog.getUpdateLogs();
    /* look for the WebLogic host that our application,
     * titled "ZUpdate", came from.  Connect to that
     * WebLogic server.
     */
    while (enum.hasMoreElements()) {
      ZACLog zl = (ZACLog)enum.nextElement();
      if ("ZUpdate".equals(zl.getZACName())) {
        t3url = "t3://" + zl.getZACHost() + ":" + zl.getZACPort() + '/';
        break;
      }
    }
    if (t3url == null) {
      p("cannot find WebLogic host for package 'ZUpdate', " +
        "defaulting to t3://localhost:7001/");
      t3url = "t3://localhost:7001/";
    }
    showStatus("WebLogic Status: connecting to " + t3url + "...");
    T3ServicesDef t3s = getT3Services(t3url);
    doLayout();
    showStatus("WebLogic Status: connected to " + t3url);
    Evaluate eval = new Evaluate("weblogic.event.evaluators.EvaluateTrue");
    Action act = new Action(this);
    EventRegistrationDef erd =
         t3s.events().getEventRegistration("WEBLOGIC.ZAC.UPDATE",
                                           eval, act, true, true, 1);
    int regid = erd.register();
  }
  
  private synchronized void nap(int milis) {
    try {
      wait(milis);
    } catch (Exception e) {}
  }
  
  /* ActionListener interface */
  public synchronized void actionPerformed(ActionEvent ev) {
    Object o = ev.getSource();
    if (o == quit) {
      System.exit(0);
    } else if (o == help) {
      helpDialog();
    } else if (o == zacstat) {
      zacDialog();
    } else if (o == flasher) {
      flasherPressed = true;
      synchronized (this) {
        notifyAll();
      }
    }
  }
  
  private void helpDialog() {
    TextDialog td = new TextDialog(getFrame(), "About ZAC demo...");
    td.appendText("ZAC demo application v. 1.0\n\n\n");
    td.appendText("(c) 1998 WebLogic Inc.\n\n\n");
    td.appendText("http://www.weblogic.com/\n");
    td.show();
  }
  
  private void zacDialog() {
    if (!ZAC.loadedByZAC()) {
      TextDialog td = new TextDialog(getFrame(), "No Update Logs Available!");
      td.appendText("WARN: no update logs are available.\n\n");
      td.appendText("Did you run with these classes in the local CLASSPATH?\n");
      td.show();
      return;
    }
    Enumeration enum = ZACLog.getUpdateLogs();
    Dialog d = new ZACLogDialog(getFrame(), enum);
    d.show();
  }
  /* WindowListener Methods */
  
  public void windowOpened(WindowEvent e) { }
  
  public void windowActivated(WindowEvent e) { }
  
  public void windowDeactivated(WindowEvent e) { }
  
  public void windowDeiconified(WindowEvent e) { }
  
  public void windowClosing(WindowEvent e) {
    Window w = e.getWindow();
    if (w == getFrame()) {
      System.exit(0);
    }
    w.setVisible(false);
    w.dispose();
  }
  public void windowClosed(WindowEvent e) {// System.exit(1); 
  }
  public void windowIconified(WindowEvent e) { }
  
  private static T3ServicesDef getT3Services(String wlUrl) 
       throws javax.naming.NamingException
  {
    T3ServicesDef t3s;
    Hashtable env = new Hashtable();
    env.put(Context.PROVIDER_URL, wlUrl);
    env.put(Context.INITIAL_CONTEXT_FACTORY,
            weblogic.jndi.WLInitialContextFactory.class.getName());
    Context ctx = new InitialContext(env);
    t3s = (T3ServicesDef) ctx.lookup("weblogic.common.T3Services");
    ctx.close();
    return(t3s);
  }

}

