import java.net.URL;
import java.util.Properties;
import java.awt.event.MouseEvent;
import java.awt.LayoutManager;
import java.awt.Dimension;
import com.sun.j3d.utils.applet.MainFrame;
import java.applet.Applet;
import java.awt.Toolkit;
import java.awt.Component;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.AWTEvent;
import java.awt.AWTEventMulticaster;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.Point;
import java.awt.MediaTracker;


// layout test
import java.io.Serializable;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;



public class CustomComponent {
  private URL BackgroungImageURL = null;
  private URL[] PropertiesFiles = null;
  private String myName = null;
  private Frame fatherFrame = null;
  private static Panel myPanel = null;

  private static MainFrame m = null ; // just for testing

  // URL[] PropertiesFile, needed for ctor variables ?
  // , java.awt.Frame father needed for ctor ??
  public CustomComponent(URL BackgroungImage , String name){
    super();
    //create father frame, should be replaced by main level frame of our application
    fatherFrame = new java.awt.Frame("father frame");
    fatherFrame.setSize(new Dimension(900,600));
    fatherFrame.setResizable(false);
    System.out.println("Ctor Entered");

    //store out backround image and our sceen name (do we want this ? )
    BackgroungImageURL = BackgroungImage ;
    myName = name;

    System.out.println("CTOR-> creating panel, setting layout and loading background image");
    // this panel is supposed to be this control grounds..
    myPanel = new java.awt.Panel();
    myPanel.setLayout(new Shop2DLayoutMgr() );


    //add our panel to the father frame
    fatherFrame.setLayout(new java.awt.BorderLayout());
    fatherFrame.add(myPanel,java.awt.BorderLayout.CENTER  );

    loadButtonImages();
    //loadBackgroudImage();

    //enable and show out panel and frame .. ->> frame should be removed from there after testing
    finalize() ;
  }

  //this methos is incharge of loading the individual component
  public void loadButtonImages(){
    try {
      ImageButton butt1 = new ImageButton(new URL("file:C:\\Java\\3DShop\\design\\gui tests\\Images\\1 button-A pressed.jpg"),new URL("file:C:\\Java\\3DShop\\design\\gui tests\\Images\\singlebutt_A_ON.jpg"));
      myPanel.add(butt1,"1butt");

      /*ImageButton butt2 = new ImageButton(new URL("file:C:\\Java\\3DShop\\design\\gui tests\\Images\\1 button-G pressed.jpg"),new URL("file:C:\\Java\\3DShop\\design\\gui tests\\Images\\1 button-G on.jpg"));
      myPanel.add(butt2,"2butt");
      myPanel.setSize(new Dimension(900,900 ));
      myPanel.setBounds(25,25,500,500);

      ImageButton butt3 = new ImageButton(new URL("file:C:\\Java\\3DShop\\design\\gui tests\\Images\\1 button-H pressed.jpg"),new URL("file:C:\\Java\\3DShop\\design\\gui tests\\Images\\1 button-H on.jpg"));
      myPanel.add(butt3,"3butt");

      //ImageButton butt4 = new ImageButton(new URL("file:C:\\Java\\3DShop\\design\\gui tests\\Images\\1 button-O pressed.jpg"),new URL("file:C:\\Java\\3DShop\\design\\gui tests\\Images\\1 button-O on.jpg"));
      //myPanel.add(butt4,"4butt");

      */
    } catch (Exception e ){
      e.printStackTrace() ;
    }
  }
  public java.awt.Panel getPanel(){
    return myPanel;
  }

  public void finalize(){
    myPanel.setVisible(true);
    myPanel.setEnabled(true);
    //myPanel.setSize() ;
    fatherFrame.setVisible(true);
    fatherFrame.setEnabled(true);
    fatherFrame.show();
  }

  // this will handle component operation for recieved click
  public void MouseActionDetected(MouseEvent event){
  }
  private void loadPropertiesFiles(){
  }

  private void loadBackgroudImage(){
    System.out.println("loadBackroundImage-> enetered");
    ImageLabel imageLabel = new ImageLabel();
    System.out.println("loadBackroundImage-> image label created");
    try {
      //create out image and store it in an image label component
            URL urlbi = new URL("file:c:\\java\\3dshop\\design\\gui tests\\Images\\singlebutt_A_ON.jpg");
      imageLabel.setImage("c:\\java\\3dshop\\design\\gui tests\\Images\\a.jpg");
      //imageLabel.setImage("c:\\java\\3dshop\\design\\gui tests\\Images\\singlebutt_A_ON.jpg");
      imageLabel.setEnabled(false);
      myPanel.add(imageLabel,"background");
    } catch (Exception e){
      e.printStackTrace() ;
    }
  }

  public static void main(String[] args){
    System.out.println("main entered");
    try {

      //URL urlbi = new URL("file:c:\\java\\3dshop\\design\\gui tests\\Images\\a.jpg");
      URL urlbi = new URL("file:c:\\java\\3dshop\\design\\gui tests\\Images\\singlebutt_A_ON.jpg");
      // the call should later add the display panel for these items..
      CustomComponent c= new CustomComponent(urlbi,"testC");
    }catch (Exception e){
      e.printStackTrace() ;
    }
  }
}


//A lightweight component which simply renders an image
class ImageLabel extends Component {
  // the image to be rendered
  Image image = null;
  boolean pressed = false ;
  Toolkit toolkit = null;



  public ImageLabel(){
    // the toolkit is an awt class enabling us to process images and display
    // them without subclassing or talking to an initialized applet
    this.enableEvents(AWTEvent.MOUSE_EVENT_MASK);
    toolkit = Toolkit.getDefaultToolkit() ;
  }

  //set the image for this component
  public void setImage(String imageFilename) throws InterruptedException {
    image = toolkit.getImage(imageFilename);
  }

  // draw the image onto the Graphics context
  public void paint(Graphics g) {
    System.out.println("image label paint");
    if (image != null)
        g.drawImage(image,getLocation().x,getLocation().y,getSize().width,getSize().height,this);
  }

  public int getImageWidth(){
    return image.getWidth(null);
  }

  public int getImageHeight(){
    return image.getHeight(null);
  }

}

class ImageButton extends ImageLabel {
  Image imageUnpressed = null; // the 'focused' image;
  Image imagePress = null;// the 'pressed' image
  boolean press = false;          //button state
  boolean inside = false;         // mouse/pointer state (inside this button's boundaries)
  ActionListener actionListener;
  MediaTracker tracker = null ;

  //construct a new ImageButton, and enable Mouse events for this component
  public ImageButton(URL pressedImage,URL unPressedImage) {
    super();
    this.enableEvents(AWTEvent.MOUSE_EVENT_MASK);
    toolkit = Toolkit.getDefaultToolkit();
    imageUnpressed = toolkit.getImage(unPressedImage);
    imagePress = toolkit.getImage(pressedImage);
    tracker = new MediaTracker(this);
    tracker.addImage(imageUnpressed,0 );
    tracker.addImage(imagePress,1 );
    try {
      tracker.waitForAll() ;
    } catch (Exception e){
      e.printStackTrace() ;
    }
  }

  public void setImageFocus(String imageFilename) throws InterruptedException {
    imageUnpressed = toolkit.getImage(imageFilename);
  }

  public void setImagePress(String imageFilename) throws InterruptedException {
    imagePress = toolkit.getImage(imageFilename);
  }

  public void paint(Graphics g) {
    System.out.println("inside image button paint , press: " + press + " in: " + inside + "panel size: " + this.getParent().getSize().toString()   );
    if (press){
      g.drawImage(imagePress,getLocation().x,getLocation().y,getSize().width,getSize().height,null);
    }
    else{
      g.drawImage(imageUnpressed,getLocation().x,getLocation().y,getSize().width,getSize().height,null);
    }
  }

  public void repaint(Graphics g){
    paint(g);
  }

  // set the specified listener for this component
  public void addActionListener(ActionListener listener) {
    actionListener = AWTEventMulticaster.add(actionListener, listener);
    enableEvents(AWTEvent.MOUSE_EVENT_MASK);
  }

  //remove the specified listener
  public void removeActionListener(ActionListener listener) {
    actionListener = AWTEventMulticaster.remove(actionListener, listener);
  }

  //handler for mouse events
  public void processMouseEvent(MouseEvent e) {

    // the button was clicked
    if (e.getID() == MouseEvent.MOUSE_PRESSED) {
      press = true;
      repaint();
      // notify listeners
      if(actionListener != null)
        actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ""));
    }

    // end of button press
    else if(e.getID() == MouseEvent.MOUSE_RELEASED) {
      press = false;
      repaint();
    }

    // Pass unhandled events to superclass.
    super.processMouseEvent(e);
  }
}

class Shop2DLayoutMgr implements LayoutManager,
                                java.io.Serializable {
  // this layout class will probably have to manage all our scene including 3D world and
  // event its parent frame . this will allow us to place everything just right. should
  // ask mark to extend xml data
  Hashtable components = new Hashtable(); // this layout components

  //should recieve xml data at this point
  public Shop2DLayoutMgr(){
    //for now im going to insert hand coded numbers into an aux hashmap, these
    //values will contain the component location and size on screen.

  }

  // actualy layout the controls for under this manager duty,
  // this should later get its data from xml and not hand coded
  public void layoutContainer(Container container){
    synchronized (container.getTreeLock()) {
      // for this test app we have 4 buttons.. assuming this class recieved all
      // 4 button components and 8 button images (on/off for each button)
      // since ill probably imlement image storage in buttonImage we will probably have
      // to transalte xml at customComponent Ctor
      Component comp = null; // will recieve component in hand
      Enumeration e = components.keys() ;
      while (e.hasMoreElements() ){
        String s = (String)e.nextElement() ;
        System.out.println("Shop2DLayoutMgr-> layoutContainer-> entered: " + s);
        // if component found
        if (components.containsKey(s)){
          comp = (Component)components.get(s);
          if (s.startsWith("1but")){
            int xpos = 95;
            int ypos = 25;
            int height = 140;
            int width = 160;
            comp.setLocation(xpos,ypos);
            comp.setSize(width,height);
            System.out.println("butt: buffered: " + comp.isDoubleBuffered() + " focus traverse: " + comp.isFocusTraversable() ) ;
          }
          else if (s.startsWith("2but")){
            int xpos = 25;
            int ypos = 25;
            int height = 150;
            int width = 150;
            comp.setLocation(xpos,ypos);
            comp.setSize(width,height);
            System.out.println("butt1 sizes: " + comp.getSize().toString());
          }
          else if (s.startsWith("3but")){
            int xpos = 85;
            int ypos = 25;
            int height = 150;
            int width = 150;
            comp.setLocation(xpos,ypos);
            comp.setSize(width,height);
          }
          else if (s.startsWith("4but")){
            int xpos = 475;
            int ypos = 25;
            int height = 150;
            int width = 150;
            comp.setLocation(xpos,ypos);
            comp.setSize(width,height);
          }
          else if (s.startsWith("background")){
            int xpos =25;
            int ypos = 25;
            int height = 120;
            int width =600;
            comp.setLocation(xpos,ypos);
            comp.setSize(width,height);
            System.out.println("background enabled: " + comp.isEnabled() );
          }
          else
            System.out.println("no if condition for current component with key: " + s);
        }
        else
          System.out.println("LayoutContainer-> comp : " + comp.toString() + " not contained");
      }
      System.out.println("walking frame: ");
        Frame f= (Frame)container.getParent() ;
        Component[] comps = f.getComponents() ;
        for (int i = 0 ; i < comps.length ; i++)
          System.out.println("item: " + comps[i].toString() );

        System.out.println("walking panel");
        comps = container.getComponents() ;
        for (int i=0 ; i<comps.length ; i++){
          System.out.println("item: " + comps[i].toString() );
        }

        container.setSize(container.getParent().getSize()  );
    }
  }

  // since minimumLayoutSize is supposed to be deprecated but the compiler still
  // demands it  added this method to call it.
  public Dimension getMinimumLayoutSize(Container container){
    return minimumLayoutSize(container);
  }

  public Dimension minimumLayoutSize(Container container){
    synchronized (container.getTreeLock()) {
      Component comp = null; // will recieve component in hand
      Dimension d= null;
      Enumeration e = components.keys() ;
      while (e.hasMoreElements() ){
        String s = (String)e.nextElement() ;
        System.out.println("Shop2DLayoutMgr-> minimumLayoutSize-> entered: " + s);
        // if component found
        if (components.containsKey(s)){
          comp = (Component)components.get(s);

            if (s.startsWith("1but"))
              return new Dimension(150,150);
            else if (s.startsWith("2but"))
              return new Dimension(150,150);
            else if (s.startsWith("3but"))
              return new Dimension(150,150);
            else if (s.startsWith("4but"))
              return new Dimension(150,150);
            else if (s.startsWith("background"))
              return new Dimension(450,150);
            else
              System.out.println("no case found for current component with key: " + s);
        }
        else
          System.out.println("LayoutContainer-> comp : " + comp.toString() + " not contained");
      }
      return null;
    }
  }

  public Dimension preferredLayoutSize(Container container){
    synchronized (container.getTreeLock()) {
      return minimumLayoutSize(container );
    }
  }

  public void removeLayoutComponent(Component component){
    synchronized (component.getTreeLock()) {
      if (components.containsValue(component ))
        components.remove(component );
    }
  }

  public void addLayoutComponent(String key,Component component){
    synchronized (component.getTreeLock()) {
    // should verify component before proceeding..
      components.put(key,component);
      System.out.println("component " + key + " added");
    }
  }
}
