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.setBounds(0,0,900,600);

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

    // this panel is supposed to be this control grounds..
    myPanel = new java.awt.Panel();
    myPanel.setLayout(new Shop2DLayoutMgr() );
    //used for frame, shouold be replaced by custom layout manager for shop2d/3d container frame


    //add our panel to the father frame
    fatherFrame.add(myPanel);

    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\\1 button-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");

      //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.getSize() ) ;
    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
      imageLabel.setImage("c:\\java\\3dshop\\design\\gui tests\\Images\\a.jpg");
      myPanel.add(imageLabel,"background");

      //fatherFrame.add(imageLabel );
    } 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\\1 button-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;
  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);
  }
}

class ImageButton extends ImageLabel {
  Image imageUnpressed = null; // the 'focused' image;
  Image imagePress = null;// the 'pressed' image
  Image imageBackBuffer = null;
  Graphics backGraphics = null ; // these one and the one above it are used for double buffering
  boolean press = false;          //button state
  boolean inside = false;         // mouse/pointer state (inside this button's boundaries)
  ActionListener actionListener;

  //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);
  }

  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) {
    update(g);
  }

  //for double buffering , override default update method and call it from also overrided paint method
  public void update(Graphics g){
    int width = getBounds().width ;
    int height = getBounds().height ;

    if (imageBackBuffer == null || imageBackBuffer.getWidth(null) !=width || imageBackBuffer.getHeight(null) !=height ){
      imageBackBuffer = createImage(width,height);
      if (imageBackBuffer != null){
        if ( backGraphics !=null )
          backGraphics.dispose() ;
        backGraphics = imageBackBuffer.getGraphics() ;
      }
    }
    if (imageBackBuffer !=null){
      java.awt.Insets insets = this.getParent().getInsets();
      //System.out.println(insets.toString() );
      //System.out.println(getParent().getParent().getInsets().toString());
      //backGraphics.fillRect(0,0,width,height);
      //backGraphics.setColor(java.awt.Color.black );
      if (press)
        backGraphics.drawImage(imagePress,getLocation().x,getLocation().y,getSize().width,getSize().height,null);
      else
        backGraphics.drawImage(imageUnpressed,getLocation().x,getLocation().y,getSize().width,getSize().height,null);
      g.drawImage(imageBackBuffer,getLocation().x,getLocation().y,getSize().width,getSize().height,null);
    }
  }


  // 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()) {
      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 = 25;
            int ypos = 25;
            int height = 250;
            int width = 250;
            comp.setBounds(xpos,ypos,width,height );
            //comp.setLocation(25,25);
            //comp.setSize(width,height);
            //System.out.println("butt2 sizes: " + comp.getSize().toString());
          }
          else if (s.startsWith("2but")){
            int xpos = 90;
            int ypos = 25;
            int height = 150;
            int width = 300;
            comp.setBounds(xpos,ypos,width,height);
            //comp.setLocation(xpos,ypos);
            //comp.setSize(width,height);
//            System.out.println("butt2 sizes: " + comp.getSize().toString());
          }
          else if (s.startsWith("3but")){
            int xpos = 265;
            int ypos = 25;
            int height = 250;
            int width = 350;
            comp.setLocation(xpos,ypos);
            comp.setSize(width,height);
          }
          else if (s.startsWith("4but")){
            int xpos = 475;
            int ypos = 25;
            int height = 150;
            int width = 300;
            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");
      }
    }
  }

  // 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");
    }
  }
}
