package com.uvigo.mhp.ui;

import com.uvigo.mhp.*;
import com.uvigo.mhp.looks.*;
import com.uvigo.mhp.xml.menu.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.xml.bind.*;
import org.havi.ui.*;
import com.uvigo.tMaestro.SCOCreator.tool.MainFrame;

public class HMenu extends JList implements Serializable, ListCellRenderer, KeyListener, ListSelectionListener, ContextHandler {
    private DefaultListModel model;
    private HGraphicLook look;
    private int backgroundMode;
    private boolean fireEventOnChange;
    
    private JAXBContext jc;
    private String configurationFile;
    
    private int current;
    private ContextManager contextManager;
    private Vector listeners;
    private String context;
    private String subcontext;
    private boolean cyclic;
    private Vector contexts;
    private Vector subcontexts;
    
    public HMenu() {
        super(new DefaultListModel());
        contextManager=null;
        listeners=new Vector();
        context="";
        subcontext="";
        contexts=new Vector();
        subcontexts=new Vector();
        current=0;
        
        try {
            jc=JAXBContext.newInstance("com.uvigo.mhp.xml.menu");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        configurationFile="";
        addKeyListener(this);
        addListSelectionListener(this);
        model=(DefaultListModel) getModel();
        setDoubleBuffered(true);
        setLayoutOrientation(javax.swing.JList.VERTICAL);
        setVisibleRowCount(1);
        setCellRenderer(this);
        setOpaque(false);
        setLook(new HGraphicLook2());
        backgroundMode=HVisible.NO_BACKGROUND_FILL;
        fireEventOnChange=false;
    }
    
    public String getConfigurationFile() {
        return configurationFile;
    }
    
    public void setConfigurationFile(String s) {
        String old=configurationFile;
        //if (!(s.equals(old))) { //Necesario eliminarlo, ya que puede cambiar el contenido del fichero y no su ruta
        
        try {
            if ((s==null) || (s=="")) return;
            
          //M: Direccionamiento relativo a "user.dir"
              String sBase= new String (MainFrame.oMainFrame.sDir+ "/");
            URL url=new URL("file:"+sBase+s);
            
            //Parte de s que corresponde a ruta (que no es fichero)
            String[] split = s.split("/");
            String sRuta=new String();
            int z=0;
            for (z=0;z<split.length-1;z++) {
                sRuta = sRuta.concat(split[z]+"/");
            }
            
            URLConnection con=url.openConnection();
            
            Unmarshaller u=jc.createUnmarshaller();
            u.setValidating(true);
            com.uvigo.mhp.xml.menu.Menu menu=(com.uvigo.mhp.xml.menu.Menu) u.unmarshal(con.getInputStream());
            java.util.List elements=menu.getMenuElement();
            
            contexts.clear();
            subcontexts.clear();
            model.clear();
            for (int i=0;i<elements.size();i++) {
                MenuElementType met=(MenuElementType) elements.get(i);
                model.addElement(new HMenuElement(met.getLabel(),"file:"+sBase+sRuta+met.getNotSelectedImage(),"file:"+sBase+sRuta+met.getSelectedImage()));
                contexts.add(met.getContextName());
                subcontexts.add(met.getComment());
            }
            
            configurationFile=s;
            firePropertyChange("configurationFile",old,s);
        } catch (Exception ex) {
            // El fichero de configuracion no se encuentra o no existe
            ex.printStackTrace();
        }
        //}
    }
    
    public int getBackgroundMode() {
        return backgroundMode;
    }
    
    public void setBackgroundMode(int bgm) {
        int old=backgroundMode;
        backgroundMode=bgm;
        if (backgroundMode==HVisible.BACKGROUND_FILL)
            setOpaque(true);
        else
            setOpaque(false);
        firePropertyChange("backgroundMode", old, bgm);
    }
    
    public boolean getFireEventOnChange() {
        return fireEventOnChange;
    }
    
    public void setFireEventOnChange(boolean b) {
        boolean old=fireEventOnChange;
        if (b!=old) {
            fireEventOnChange=b;
            firePropertyChange("fireEventOnChange", new Boolean(old), new Boolean(b));
        }
    }
    
    public void setLook(HGraphicLook look) {
        HGraphicLook old=look;
        this.look=look;
        firePropertyChange("look", old, look);
    }
    
    public HGraphicLook getLook() {
        return look;
    }
    
    public String getSelectedLabel() {
        HMenuElement e=(HMenuElement) getSelectedValue();
        if (e==null)
            return null;
        return e.getLabel();
    }
    
    public Component getListCellRendererComponent(
            JList list,
            Object value,
            int index,
            boolean isSelected,
            boolean cellHasFocus) {
        if (!(value instanceof HMenuElement))
            return new JLabel("");
        
        HMenuElement element=(HMenuElement) value;
        try {
            HButton b=new HButton();
            if (isSelected) {
                Image img=element.getSelectedImage();
                b.setGraphicContent(img, HState.ALL_STATES);
                b.setTextContent(element.getLabel(), HState.ALL_STATES);
                b.setBackgroundMode(HVisible.BACKGROUND_FILL);
                b.setBackground(getSelectionBackground());
                b.setForeground(getSelectionForeground());
            } else {
                Image img=element.getNotSelectedImage();
                b.setGraphicContent(img, HState.ALL_STATES);
                b.setTextContent(element.getLabel(), HState.ALL_STATES);
                b.setBackgroundMode(getBackgroundMode());
                b.setBackground(getBackground());
                b.setForeground(getForeground());
            }
            
            if (look!=null)
                b.setLook(look);
            
            return b;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }
    
    public void keyPressed(java.awt.event.KeyEvent keyEvent) {
        if (keyEvent.getKeyCode()==KeyEvent.VK_ENTER)
            fireEvent();
    }
    
    public void keyReleased(java.awt.event.KeyEvent keyEvent) {
    }
    
    public void keyTyped(java.awt.event.KeyEvent keyEvent) {
    }
    
    public void valueChanged(ListSelectionEvent e) {
        String old=context;
        context=(String) contexts.get(getSelectedIndex());
        subcontext=(String) subcontexts.get(getSelectedIndex());
        ensureIndexIsVisible(getSelectedIndex());
        fireSubcontextEvent();
        if ((fireEventOnChange) && (!(context.equals(old))))
            fireEvent();
    }
    
    ///////////////////////////////////////////////////////////////////////////////7
    // GESTION DE CONTEXTOS
    ///////////////////////////////////////////////////////////////////////////////7
    
    public String getContext() {
        return context;
    }
    
    public void setContext(String s) {
        if ((s==null) || (s.equals("")))
            return;
        
        if (model.size()==0)
            return;
        
        for (int i=0;i<model.size();i++) {
            if (contexts.get(i).equals(s)) {
                switchTo(i);
                return;
            }
        }
        //System.out.println("Contexto desconocido");
    }
    
    public void gotoFirstContext() {
        switchTo(0);
    }
    
    public void gotoLastContext() {
        switchTo(model.size()-1);
    }
    
    public void gotoNextContext() {
        if ((!cyclic) && (getSelectedIndex()==(model.size()-1)))
            return;
        
        switchTo((current+1)%model.size());
    }
    
    public void gotoPreviousContext() {
        if ((!cyclic) && (getSelectedIndex()==0))
            return;
        
        switchTo((current-1+model.size())%model.size());
    }
    
    public boolean isCyclic() {
        return cyclic;
    }
    
    public void setCyclic(boolean b) {
        boolean old=cyclic;
        if (old!=b) {
            cyclic=b;
            firePropertyChange("cyclic",new Boolean(old), new Boolean(b));
        }
    }
    
    public ContextManager getContextManager() {
        return contextManager;
    }
    
    public void setContextManager(ContextManager c) {
        ContextManager old=contextManager;
        
        // si se indica el mismo ContextManager que estaba configurado, no se hace nada
        if (c==old)
            return;
        
        // si habia alguno configurado, nos damos de baja
        if (old!=null) {
            old.remove(this);
            removeContextListener(old);
        }
        
        // nos registramos en el nuevo ContextManager, pero solo si no es null
        if (c!=null) {
            addContextListener(c);
            c.add(this);
        }
        
        contextManager=c;
        firePropertyChange("contextManager",old,c);
    }
    
    
    public void addContextListener(ContextListener c) {
        if (!(listeners.contains(c)))
            listeners.add(c);
    }
    
    public void removeContextListener(ContextListener c) {
        if (listeners.contains(c))
            listeners.remove(c);
    }
    
    private void switchTo(int i) {
        String old=context;
        if (current==i) return;
        
        context=(String) contexts.get(i);
        current=i;
        removeListSelectionListener(this);
        setSelectedIndex(i);
        ensureIndexIsVisible(i);
        addListSelectionListener(this);
        if (!(context.equals(old)))
            fireEvent();
    }
    
    private void fireEvent() {
        for (int i=0;i<listeners.size();i++) {
            ContextListener c=(ContextListener) listeners.get(i);
            c.contextChanged(new ContextEvent(this, context));
        }
    }
    
    private void fireSubcontextEvent() {
        for (int i=0;i<listeners.size();i++) {
            ContextListener c=(ContextListener) listeners.get(i);
            c.subcontextEntered(new ContextEvent(this, subcontext));
        }
    }
    
    public String getSubcontext() {
        return subcontext;
    }
}