/*
 Eteria IRC Client, an RFC 1459 compliant client program written in Java.
 Copyright (C) 2000-2001  Javier Kohen <jkohen at tough.com>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
 import java.awt.*;
 import java.awt.event.*;
 import java.io.IOException;
 import java.util.Enumeration;
 import java.net.URL;
 import java.net.MalformedURLException;
 
 
 import ar.com.jkohen.awt.*;
 import ar.com.jkohen.awt.event.*;
 import ar.com.jkohen.irc.Channel;
 import ar.com.jkohen.irc.RFC1459;
 import ar.com.jkohen.util.Resources;
 import ar.com.jkohen.util.CollatedHashtable;
 
 public class ChatPanelContainer extends Panel implements ActionListener, MouseListener, TextListener
 {
 	private EIRC eirc;
 	private Resources res;
 
 	private CollatedHashtable panels;
 	private String status_tag;
 	private String tab_under_menu;
 	private ChatPanel visible_panel;
 
 	private CardLayout container_layout;
 	private BorderedPanel container;
 	private ChatTabs tabs;
 	private PopupMenu tabs_popup;
 	private MenuItem close_item;
 	private ImageCanvas label;
 	private BorderedPanel bottom_panel;
 	private ImageButton shift_left;
 	private ImageButton shift_right;
 	
 	public ChatPanelContainer(EIRC eirc)
 	{
 		this.eirc = eirc;
 		this.panels = new CollatedHashtable(RFC1459.getCollator());
 
 		GridBagLayout gb = new GridBagLayout();
 		GridBagConstraints gbc = new GridBagConstraints();
 
 		setLayout(gb);
 
 		this.container = new BorderedPanel();
 		gbc.weighty = 1.0;
 		gbc.weightx = 1.0;
 		gbc.fill = GridBagConstraints.BOTH;
 		gbc.gridy = 0;
 		gb.setConstraints(container, gbc);
 		add(container);
 		gbc.weightx = 0.0;
 		gbc.weighty = 0.0;
 
 		gbc.gridy = 1;
 
 		bottom_panel = new BorderedPanel(res.getString("bottom_panel"));
 		GridBagLayout bottom_gb = new GridBagLayout();
 		GridBagConstraints bottom_gbc = new GridBagConstraints();
 		bottom_panel.setLayout(bottom_gb);
 
 		/* Bottom Panel begins here. */
 		bottom_gbc.anchor = GridBagConstraints.NORTH;
 
 		Image i = res.getImage("tabs.logo");
 		if (i != null)
 		{
 			label = new ImageCanvas(i);
 			bottom_gbc.gridheight = GridBagConstraints.REMAINDER;
 			bottom_gb.setConstraints(label, bottom_gbc);
 			bottom_panel.add(label);
 			bottom_gbc.gridheight = 1;
 		}
 
 	  	this.tabs = new ChatTabs(eirc);
 		bottom_gbc.weightx = 1.0;
 		bottom_gbc.fill = GridBagConstraints.HORIZONTAL;
 		bottom_gbc.gridheight = GridBagConstraints.REMAINDER;
 		bottom_gb.setConstraints(tabs, bottom_gbc);
 		bottom_panel.add(tabs);
 		bottom_gbc.gridheight = 1;
 		bottom_gbc.fill = GridBagConstraints.NONE;
 		bottom_gbc.weightx = 0.0;
 
 		this.shift_left = new ImageButton(false);
 		shift_left.setEnabled(false);
 		shift_left.setIcon(res.getImage("tabs.icon.shift_left"));
 		bottom_gb.setConstraints(shift_left, bottom_gbc);
 		bottom_panel.add(shift_left);
 
 		bottom_gbc.gridy = 1;
 
 		this.shift_right = new ImageButton(false);
 		shift_right.setEnabled(false);
 		shift_right.setIcon(res.getImage("tabs.icon.shift_right"));
 		bottom_gb.setConstraints(shift_right, bottom_gbc);
 		bottom_panel.add(shift_right);
 		
 		/* Bottom Panel ends here. */
 
 		gbc.weightx = 1.0;
 		gbc.fill = GridBagConstraints.HORIZONTAL;
 		gb.setConstraints(bottom_panel, gbc);
 		add(bottom_panel);
 
 		tabs.setImage(ChatTabs.CHAN, ChatTabs.NORMAL, ChatTabs.LEFT, res.getImage("tabs.normal.chan"));
 		tabs.setImage(ChatTabs.CHAN, ChatTabs.NORMAL, ChatTabs.CENTER, res.LARGE_NORMAL);
 		tabs.setImage(ChatTabs.CHAN, ChatTabs.CURRENT, ChatTabs.LEFT, res.getImage("tabs.current.chan"));
 		tabs.setImage(ChatTabs.CHAN, ChatTabs.CURRENT, ChatTabs.CENTER, res.LARGE_PRESSED);
 		tabs.setImage(ChatTabs.CHAN, ChatTabs.ALARM, ChatTabs.LEFT, res.getImage("tabs.alarm.chan"));
 		tabs.setImage(ChatTabs.CHAN, ChatTabs.ALARM, ChatTabs.CENTER, res.LARGE_ALERT);
 
 		tabs.setImage(ChatTabs.PRIV, ChatTabs.NORMAL, ChatTabs.LEFT, res.getImage("tabs.normal.private"));
 		tabs.setImage(ChatTabs.PRIV, ChatTabs.NORMAL, ChatTabs.CENTER, res.LARGE_NORMAL);
 		tabs.setImage(ChatTabs.PRIV, ChatTabs.CURRENT, ChatTabs.LEFT, res.getImage("tabs.current.private"));
 		tabs.setImage(ChatTabs.PRIV, ChatTabs.CURRENT, ChatTabs.CENTER, res.LARGE_PRESSED);
 		tabs.setImage(ChatTabs.PRIV, ChatTabs.ALARM, ChatTabs.LEFT, res.getImage("tabs.alarm.private"));
 		tabs.setImage(ChatTabs.PRIV, ChatTabs.ALARM, ChatTabs.CENTER, res.LARGE_ALERT);
 		
 		tabs.setImage(ChatTabs.SERV, ChatTabs.NORMAL, ChatTabs.LEFT, res.getImage("tabs.normal.server"));
 		tabs.setImage(ChatTabs.SERV, ChatTabs.NORMAL, ChatTabs.CENTER, res.LARGE_NORMAL);
 		tabs.setImage(ChatTabs.SERV, ChatTabs.CURRENT, ChatTabs.LEFT, res.getImage("tabs.current.server"));
 		tabs.setImage(ChatTabs.SERV, ChatTabs.CURRENT, ChatTabs.CENTER, res.LARGE_PRESSED);
 		tabs.setImage(ChatTabs.SERV, ChatTabs.ALARM, ChatTabs.LEFT, res.getImage("tabs.alarm.server"));
 		tabs.setImage(ChatTabs.SERV, ChatTabs.ALARM, ChatTabs.CENTER, res.LARGE_ALERT);
 		
 		this.container_layout = new CardLayout();
 		container.setLayout(container_layout);
 
 		this.tabs_popup = new PopupMenu();
 		add(tabs_popup);
 		
 		if (label != null)
 			label.addMouseListener(this);
 			
 		tabs.addActionListener(this);
 		tabs.addMouseListener(this);
 		shift_left.addActionListener(this);
 		shift_right.addActionListener(this);
 		tabs_popup.addActionListener(this);
 	}
 	
 	private void createMenu(PopupMenu pop, String tag)
 	{
 		pop.removeAll();
 
 		MenuItem mi = null;
 		mi = new MenuItem(res.getString("close.privates"));
 		mi.setActionCommand("close.privates");
 		pop.add(mi);
 		mi = new MenuItem(res.getString("close.unread"));
 		mi.setActionCommand("close.unread");
 		pop.add(mi);
 		mi = new MenuItem(res.getString("close.channels"));
 		mi.setActionCommand("close.channels");
 		pop.add(mi);
 	
 		if (tag != null && !tag.equals(status_tag))
 		{
 			pop.addSeparator();
 /*
 			mi = new MenuItem(res.getString("open") + " " + tag);
 			mi.setActionCommand("open");
 			pop.add(mi);
 */
 			mi = new MenuItem(res.getString("close") + " " + tag);
 			mi.setActionCommand("close");
 			pop.add(mi);
 		}
 	}
 
 	public void add(ChatPanel cp, String tag)
 	{
 		add(cp, tag, false);
 	}
 
 	public void add(ChatPanel cp, String tag, boolean is_status)
 	{
 		if (is_status)
 		{
 			if (status_tag != null)
 			{
 				throw new IllegalArgumentException("already have a status panel");
 			}
 			this.status_tag = tag;
 		}
 
 		synchronized (this)
 		{
 			panels.put(tag, cp);
 			container.add(cp, tag.toLowerCase());
 			tabs.add(tag);
 		}
 
 		updateShiftButtons();
 
 		cp.addTextListener(this);
 	}
 
 	public void addPanel(ChatPanel cp, String tag)
 	{
 		synchronized (this)
 		{
 			panels.put(tag, cp);
 			container.add(cp, tag.toLowerCase());
 		}
 
 		cp.addTextListener(this);
 	}
 	
 	public synchronized void showPanel(String tag)
 	{
 		ChatPanel cp = this.visible_panel = (ChatPanel) panels.get(tag);
 		
 		container_layout.show(container, tag.toLowerCase());
 		cp.requestFocus();
 		tabs.notVisible();
 		
 		container.setTag(cp.getTitle());
 	}
 	
 	public void remove(String tag)
 	{
 		if (tag.equals(visible_panel))
 			this.visible_panel = null;
 
 		synchronized (this)
 		{
 			tabs.remove(tag);
 			
 			Component c = (Component) panels.remove(tag);
 			if (c == null) return;
 			container.remove(c);
 
 			if (tag.equals(status_tag))
 				this.status_tag = null;
 
 			String new_tab = tabs.getCurrent();
 			if (new_tab != null)
 			{
 				show(new_tab);
 			}
 			else if (panels.containsKey(status_tag))
 			{
 				show(status_tag);
 			}
 		}
 
 		updateShiftButtons();
 	}
 
 	public synchronized void rename(String old_tag, String tag)
 	{
 		ChatPanel cp = (ChatPanel) panels.get(old_tag);
 
 		// Removing the old panel isn't necessary: adding it under a different tag has the same effect.
 		container.add(cp, tag.toLowerCase());
 		if (old_tag.equals(tabs.getVisible()))
 			container_layout.show(container, tag.toLowerCase());
 
 		cp.setPanelTag(tag);
 		panels.put(tag, cp);
 		panels.remove(old_tag);
 
 		tabs.rename(old_tag, tag);
 	}
 
 	public void setTitle(String tag, String title)
 	{
 		ChatPanel cp = (ChatPanel)panels.get(tag);
 		cp.setTitle(title);
 		
 		if(this.visible_panel == cp)
 			container.setTag(title);
 	}
 	
 	public synchronized void show(String tag)
 	{
 		ChatPanel cp = this.visible_panel = (ChatPanel)panels.get(tag);
 
 		container_layout.show(container, tag.toLowerCase());
 		cp.requestFocus();
 		cp.setRead(true);
 
 		tabs.setAlarm(tag, false);
 		tabs.makeVisible(tag);
 		
 		container.setTag(cp.getTitle());
 	}
 
 	private void updateShiftButtons()
 	{
 		int tabs_width = tabs.getSize().width;
 		boolean enabled = tabs_width > 0 && tabs_width < tabs.getPreferredSize().width;
 
 		shift_left.setEnabled(enabled);
 		shift_right.setEnabled(enabled);
 	}
 
 	public ChatPanel getVisible()
 	{
 		return visible_panel;
 	}
 
 	public void setFont(Font f)
 	{
 		super.setFont(f);
 		container.setFont(f);
 		bottom_panel.setFont(f);
   		tabs.setFont(f);
 		
 		// Popup menu font
 		for (int i = 0; i < tabs_popup.getItemCount(); i++)
 			tabs_popup.getItem(i).setFont(f);
 	}
 	
 	public void setForeground(Color c)
 	{
 		super.setForeground(c);
 		container.setForeground(c);
 		bottom_panel.setForeground(c);
   		tabs.setForeground(c);
   		if(label != null)
   			label.setForeground(c);
 	}
 
 	public void setBackground(Color c)
 	{
 		super.setBackground(c);
 		container.setBackground(c);
 		bottom_panel.setBackground(c);
   		tabs.setBackground(c);
   		if(label != null)
 	  		label.setBackground(c);
 		shift_left.setBackground(c);
 		shift_right.setBackground(c);
 	}
 
 	public void setBounds(int x, int y, int w, int h)
 	{
 		super.setBounds(x, y, w, h);
 		updateShiftButtons();
 	}
 
 	public void actionPerformed(ActionEvent ev)
 	{
 		Object source = ev.getSource();
 
 		if (source.equals(tabs))
 		{
 			show(ev.getActionCommand());
 		}
 		else if (source.equals(shift_left))
 		{
 			tabs.shiftLeft();
 		}
 		else if (source.equals(shift_right))
 		{
 			tabs.shiftRight();
 		}
 		else if (source instanceof MenuItem)
 		{
 			String cmd = ev.getActionCommand();
 
 			if (cmd.equals("open"))
 			{
 				show(tab_under_menu);
 			}
 			else if (cmd.equals("close"))
 			{
 				ChatPanel cp = (ChatPanel) panels.get(tab_under_menu);
 				if (cp != null)
 					eirc.close(tab_under_menu);
 			}
 			else if (cmd.equals("close.privates"))
 			{
 				eirc.closeAllPrivates();
 			}
 			else if (cmd.equals("close.unread"))
 			{
 				eirc.closeUnreadPrivates();
 			}
 			else if (cmd.equals("close.channels"))
 			{
 				eirc.closeAllChannels();
 			}
 		}
 	}
 	
 	public void mouseClicked(MouseEvent ev)
 	{
 	}
 
 	public void mouseReleased(MouseEvent ev)
 	{
 	}
 
 	public void mousePressed(MouseEvent ev)
 	{
 		Object source = ev.getSource();
 
 		if (source.equals(tabs))
 		{
 			if (ev.isPopupTrigger() || 0 != (ev.getModifiers() & MouseEvent.BUTTON3_MASK))
 			{
 				// WORKAROUND: #27 MSIE doesn't set popupTrigger.
 				String tab = tabs.getTabAt(ev.getPoint());
 				tab_under_menu = tab;
 
 				createMenu(tabs_popup, tab);
 				tabs_popup.show(tabs, ev.getX(), ev.getY());
 			}
 		}
 
 		if (source.equals(label))
 		{
 			try
 			{
 				eirc.visitURL(new URL(res.getLabel("tabs.url")));
  			}
 			catch (MalformedURLException e) {}
 		}
 	}
 
 	public void mouseEntered(MouseEvent ev)
 	{
 		Object source = ev.getSource();
 		if (source.equals(label))
 			setCursor(new Cursor(Cursor.HAND_CURSOR));
 	}
 
 	public void mouseExited(MouseEvent ev)
 	{
 		setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 	}
 
 	public void textValueChanged(TextEvent e)
 	{
 		ChatPanel cp = (ChatPanel) e.getSource();
 		String tag = cp.getPanelTag();
 
 		// Don't try to set an alarm on a recently closed panel.
 		synchronized (this)
 		{
 			if (panels.containsKey(tag))
 			{
 				tabs.setAlarm(tag, true);
 				cp.setRead(false);
 			}
 		}
 	}
 }