/*
 Eteria IRC Client, an RFC 1459 compliant client program written in Java.
 Copyright (C) 2001  Christian Buck <cbuck at lantis.de>
 
 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.net.MalformedURLException;
 import java.net.URL;
 import java.io.IOException;
 import java.util.*;
 import java.text.Collator;
 import java.text.MessageFormat;
 import java.text.ParseException;
 
 import ar.com.jkohen.irc.Channel;
 import ar.com.jkohen.irc.User;
 import ar.com.jkohen.irc.MircMessage;
 import ar.com.jkohen.util.Resources;
 import ar.com.jkohen.util.ConfigurationProperties;
 import ar.com.jkohen.awt.ChatPanel;
 import ar.com.jkohen.awt.NickInfo;
 import ar.com.jkohen.awt.ImageButton;
 import ar.com.jkohen.awt.BorderedPanel;
 import com.splendid.awtchat.*;
 
 class WhoListWindow extends ChatPanel implements ActionListener, ItemListener, HyperlinkReceiver, Observer
 {
 	private EIRC eirc;
 	private String title;
 	private SmileyTextArea text_canvas;
 	private Vector users;
 
 	public static final int SORT_BYNICK = 0;
 	public static final int SORT_BYAGE = 1;
 	public static final int SORT_BYLOCATION = 2;
 	public static final int SORT_BYDOMAIN = 3;
 	public static final int SORT_BYSEX = 4;
 	
 	private static int sort_criteria = SORT_BYNICK;
 	private Collator collator;
 	
 	private static boolean FILTER_MALE = false;
 	private static boolean FILTER_FEMALE = false;
 	private static boolean FILTER_UNKNOWN = true;
 	
 	private Resources res;
 	protected static final String age_string = Resources.getString("who_list.age");
 	
 	Checkbox sort_0, sort_1, sort_2, sort_3, sort_4;
 	Checkbox male, female, unknown, invisible;
 	
 	BorderedPanel panel;
 	ImageButton b;
 	
 	protected static final MessageFormat MALE_FORMAT = new MessageFormat(Resources.getString("msg.male"));
 	protected static final MessageFormat FEMALE_FORMAT = new MessageFormat(Resources.getString("msg.female"));
 	protected static final MessageFormat UNKNOWN_FORMAT = new MessageFormat(Resources.getString("msg.unknown"));
 	
 
 	public WhoListWindow(EIRC eirc, String title)
 	{
 		super(title);
 		text_canvas = new SmileyTextArea(this, null);
 
 		this.eirc = eirc;
 		this.title = title;
 		this.collator = Collator.getInstance();
 		
 		text_canvas.setMode(eirc.scrollSpeed());
 		text_canvas.setBufferlen(1000);
 		text_canvas.setBreaks(false);
 		int tabs[] = {-1, 200, 250, 320};
 		text_canvas.setTabs(tabs);
 
 		GridBagLayout gb = new GridBagLayout();
 		GridBagConstraints gbc = new GridBagConstraints();
 		setLayout(gb);
 
 		gbc.insets = new Insets(2, 2, 2, 2);
 
 		gbc.gridx = 0;
 		gbc.gridy = 0;
 		gbc.gridwidth = 1;
 		gbc.gridheight = 2;
 		gbc.anchor = GridBagConstraints.CENTER;
 		gbc.fill = GridBagConstraints.BOTH;
 		gbc.weighty = 1;
 	  	gbc.weightx = 1;
 		gb.setConstraints(text_canvas, gbc);
 		add(text_canvas);
 		
 		invisible = new Checkbox(res.getString("who_list.invisible"));
 	  	gbc.weightx = 0;
 		gbc.weighty = 0;
 		gbc.fill = GridBagConstraints.NONE;
 		gbc.gridheight = 1;
 		gbc.gridx++;
 		gbc.anchor = GridBagConstraints.NORTH;
 		gb.setConstraints(invisible, gbc);
 		add(invisible);
 		
 		
 		panel = new BorderedPanel(Resources.getString("who_list.frame"));
 		GridBagLayout gb2 = new GridBagLayout();
 		GridBagConstraints gbc2 = new GridBagConstraints();
 		panel.setLayout(gb2);
 
 		gbc2.weightx = 1.0;
 		gbc2.insets = new Insets(0, 2, 0, 2);
 
 		gbc2.gridx = 0;
 		gbc2.gridy = 0;
 		gbc2.anchor = GridBagConstraints.WEST;
 		Label l = new Label(res.getString("who_list.sort") + " :");
 		gb2.setConstraints(l, gbc2);
 		panel.add(l);
 		
 		CheckboxGroup sort_group = new CheckboxGroup();
 		
 		gbc2.gridy++;
 		sort_0 = new Checkbox(res.getString("who_list.sort.1"), sort_group, (sort_criteria == SORT_BYNICK));
 		gb2.setConstraints(sort_0, gbc2);
 		panel.add(sort_0);
 		
 		gbc2.gridy++;
 		sort_1 = new Checkbox(res.getString("who_list.sort.2"), sort_group, (sort_criteria == SORT_BYAGE));
 		gb2.setConstraints(sort_1, gbc2);
 		panel.add(sort_1);
 
 		gbc2.gridy++;
 		sort_2 = new Checkbox(res.getString("who_list.sort.3"), sort_group, (sort_criteria == SORT_BYSEX));
 		gb2.setConstraints(sort_2, gbc2);
 		panel.add(sort_2);
 
 		gbc2.gridy++;
 		sort_3 = new Checkbox(res.getString("who_list.sort.4"), sort_group, (sort_criteria == SORT_BYDOMAIN));
 		gb2.setConstraints(sort_3, gbc2);
 		panel.add(sort_3);
 		
 		gbc2.gridy++;
 		sort_4 = new Checkbox(res.getString("who_list.sort.5"), sort_group, (sort_criteria == SORT_BYLOCATION));
 		gb2.setConstraints(sort_4, gbc2);
 		panel.add(sort_4);
 		
 		gbc2.gridy++;
 		gbc2.gridwidth = 2;
 		gbc2.anchor = GridBagConstraints.CENTER;
 		b = new ImageButton(res.getString("who_list.refresh"));
 		b.setWaitType();
 		b.setEnabled(true);
 		b.setActionCommand("list");
 		gb2.setConstraints(b, gbc2);
 		
 		gbc.anchor = GridBagConstraints.NORTH;
 		gb.setConstraints(panel, gbc);
 		panel.add(b);
 		
 		gbc2.gridy = 0;
 		gbc2.gridx++;
 		gbc2.gridwidth = 1;
 
 		l = new Label(res.getString("who_list.check") + " :");
 		gbc2.anchor = GridBagConstraints.WEST;
 		gb2.setConstraints(l, gbc2);
 		panel.add(l);
 		
  		gbc2.gridy++;
 		male = new Checkbox(res.getString("who_list.male"), !FILTER_MALE);
 		gb2.setConstraints(male, gbc2);
 		panel.add(male);
 		
 		gbc2.gridy++;
 		female = new Checkbox(res.getString("who_list.female"), !FILTER_FEMALE);
 		gb2.setConstraints(female, gbc2);
 		panel.add(female);
 		
 		gbc2.gridy++;
 		unknown = new Checkbox(res.getString("who_list.unknown"), !FILTER_UNKNOWN);
 		gb2.setConstraints(unknown, gbc2);
 		panel.add(unknown);
 		
 
 		gbc.weightx = 0;
 	  	gbc.weighty = 1;
 		gbc.gridy++;
 		gb.setConstraints(panel, gbc);
 		add(panel);
 
 		b.addActionListener(this);
 		sort_0.addItemListener(this);
 		sort_1.addItemListener(this);
 		sort_2.addItemListener(this);
 		sort_3.addItemListener(this);
 		sort_4.addItemListener(this);
 		male.addItemListener(this);
 		female.addItemListener(this);
 		unknown.addItemListener(this);
 		invisible.addItemListener(this);
 	}
 
 	public void clear()
 	{
 		text_canvas.clear();
 	}
 	
 	public void setEnabled(boolean enabled)
 	{
 		b.setEnabled(enabled);
 	}
 	
 	public void loadUsers(Vector data)
 	{
 //		Vector users = NickInfo.getList();
 		this.users = data;		
 		display();
 	}
 		
 	private void display()
 	{
 		text_canvas.setMode(text_canvas.SAFE);
 		text_canvas.clear();
 		
 		if (users != null)
 		{
 			sort(users);
 			
 			boolean display = true;
 			
 		  	for (Enumeration e = users.elements(); e.hasMoreElements(); )
 		  	{
 				String nick = e.nextElement().toString();
 				
 				int a = NickInfo.getAge(nick);
 				String age = (a > 0 ? String.valueOf(a) + " " + age_string : "-");
 					
 				String desc = NickInfo.getLocation(nick);
 				String country = NickInfo.getCountry(nick);
 				
 				display = true;
 				MessageFormat mf;
 				switch(NickInfo.getSex(nick))
 				{
 				case NickInfo.SEX_MALE:
 					mf = MALE_FORMAT;
 					if (FILTER_MALE)
 						display = false;
 					break;
 				case NickInfo.SEX_FEMALE:
 					mf = FEMALE_FORMAT;
 					if (FILTER_FEMALE)
 						display = false;
 					break;
 				default:
 					mf = UNKNOWN_FORMAT;
 					if (FILTER_UNKNOWN)
 						display = false;
 					break;
 				}
 				
 				if (invisible.getState() && eirc.getNick().equals(nick))
 					display = false;
 
 				if (display)
 				{
 					Object o[] = { "", nick, "", MircMessage.COLOR + "3 " + age + MircMessage.COLOR + "12 " + country + MircMessage.RESET + desc };
 					text_canvas.appendNickInfo(mf.format(o), true, nick);
 				}
 			}
 		}
 		
 		text_canvas.setMode(eirc.scrollSpeed());
 		text_canvas.home();
 		b.setEnabled(true);
 	}
 	
 	// Sorting algorithm from James Gosling
 	
 	private void sort(Vector v)
 	{
 		sort(v, 0, v.size() - 1);
 	}
 	
 	private void sort(Vector v, int i, int j)
 	{
 		int k = i;
 		int l = j;
 		if(k >= l)
 			return;
 		else
 			if(k == l - 1)
 			{
 				Object a = v.elementAt(k);
 				Object b = v.elementAt(l);
 				if (compare(a, b) < 0)
 				{
 					v.setElementAt(b, k);
 					v.setElementAt(a, l);
 				}
 			}
 			
 		Object a = v.elementAt((k + l) / 2);
 		v.setElementAt(v.elementAt(l), (k + l) / 2);
 		v.setElementAt(a, l);
 		
 		while(k < l) 
 		{
 			while(k < l && compare(a, v.elementAt(k)) >= 0) 
 				k++;
 			while(k < l && compare(a, v.elementAt(l)) <= 0)
 				l--;
 			if(k < l)
 			{
 				Object o = v.elementAt(k);
 				v.setElementAt(v.elementAt(l), k);
 				v.setElementAt(o, l);
 			}
 		}
 		v.setElementAt(v.elementAt(l), j);
 		v.setElementAt(a, l);
 				
 		sort(v, i, k - 1);
 		sort(v, l + 1, j);
 	}
 	
 	private int compare(Object o1, Object o2)
 	{
 		int comp = 0;
 		String nick1 = o1.toString();
 		String nick2 = o2.toString();
 			
 		switch (sort_criteria)
 		{
    		case SORT_BYNICK:
 	  		comp = collator.compare(nick1, nick2);
 	  		break;
 		case SORT_BYAGE:
 			comp = NickInfo.getAge(nick1) - NickInfo.getAge(nick2);
 			break;
 		case SORT_BYLOCATION:
 			comp = collator.compare(NickInfo.getLocation(nick1), NickInfo.getLocation(nick2));
 			break;
 		case SORT_BYDOMAIN:
 			comp = collator.compare(NickInfo.getCountry(nick1), NickInfo.getCountry(nick2));
 			break;
 		case SORT_BYSEX:
 		default:
 			comp = NickInfo.getSex(nick2) - NickInfo.getSex(nick1);
 			break;
 		}
 		return(comp);
 	}
 	
 	public void updateBackground(Container ct, Color cl)
 	{
 		ct.setBackground(cl);
 		Component cp[] = ct.getComponents();
 		for (int i = 0; i < cp.length; i++)
 		{
 			if (cp[i] instanceof Container)
 				updateBackground((Container)cp[i], cl);
 			else
 				if (!(cp[i] instanceof TextField))
 					cp[i].setBackground(cl);
 		}
 	}
 	
 	public void setBackground(Color c)
 	{
 		super.setBackground(c);
 		invisible.setBackground(c);
 		updateBackground((Container)panel, c);
 	}
 
 	public void setTextBackground(Color c)
 	{
 		text_canvas.setBackground(c);
 	}
 	
 	public void setForeground(Color c)
 	{
 		super.setForeground(c);
 	}
 
 	public void setSelectedBackground(Color c)
 	{
 		text_canvas.setSelectedBackground(c);
 	}
 
 	public void setSelectedForeground(Color c)
 	{
 //		visualTree.setSelectedForeground(c);
 	}
 
 	public void setFont(Font f)
 	{
 		super.setFont(f);
 		text_canvas.setFont(f);
 		b.setFont(f);
 	}
 	
 	public void actionPerformed(ActionEvent ev)
 	{
 		String ac = ev.getActionCommand();
 		
 		if (ac.equals("list"))
 		{
 			b.setEnabled(false);
 			NickInfo.clear();
 			
 			String p1[] = { };
 			eirc.sendMessage("LUSERS", p1);
 
 			String p2[] = { "*" };
 			eirc.sendMessage("WHO", p2);
 		}
 	}
 	
 	public void itemStateChanged(ItemEvent ev)
 	{
 		if (ev.getSource() == sort_0)
 			sort_criteria = SORT_BYNICK;
 		if (ev.getSource() == sort_1)
 			sort_criteria = SORT_BYAGE;
 		if (ev.getSource() == sort_2)
 			sort_criteria = SORT_BYSEX;
 		if (ev.getSource() == sort_3)
 			sort_criteria = SORT_BYDOMAIN;
 		if (ev.getSource() == sort_4)
 			sort_criteria = SORT_BYLOCATION;
 		if (ev.getSource() == male)
 			FILTER_MALE = !male.getState();
 		if (ev.getSource() == female)
 			FILTER_FEMALE = !female.getState();
 		if (ev.getSource() == unknown)
 			FILTER_UNKNOWN = !unknown.getState();
 			
 		if (ev.getSource() == invisible)
 		{
 			String p[] = { eirc.getNick(), (invisible.getState() ? "+" : "-") + "i" };
 			eirc.sendMessage("MODE", p);
 		}
 			
 		display();
 	}
 	
 	public void update(Observable o, Object arg)
 	{
 		ConfigurationProperties props = (ConfigurationProperties) o;
 
 		if (arg == null || arg.equals("scroll_speed"))
 			text_canvas.setMode(props.getInt("scroll_speed"));
 	}
 
 	public void handleHyperlink(String link)
 	{
 		if (Channel.isChannel(link))
 		{
 			joinChannel(link);
  		}
  		else
  		{
 	 	   try
 	 	   {
 				visitURL(new URL(link));
 	 	   }
 	 	   catch (MalformedURLException e)
 	 	   {
 	 	   }
 		}
 	}
 	
 	public void handleNick(String nick)
 	{
 		eirc.openPrivate(nick);
 		eirc.showPanel(nick);
 	}
 	
 	protected void visitURL(URL url)
 	{
 		eirc.visitURL(url);
 	}
 	
 	protected void joinChannel(String name)
 	{
 		eirc.joinChannel(name);
 	}
 }