/*
 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.net.URL;
 import java.net.MalformedURLException;
 import java.io.*;
 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.awt.BorderedPanel;
 import ar.com.jkohen.awt.ChatPanel;
 import ar.com.jkohen.awt.ImageButton;
 import ar.com.jkohen.awt.MircSmileyTextArea;
 import ar.com.jkohen.util.Resources;
 import ar.com.jkohen.util.ConfigurationProperties;
 import com.splendid.awtchat.*;
 
 
 public class ChanListWindow extends ChatPanel implements ActionListener, ItemListener, HyperlinkReceiver, Observer, CopyText
 {
 	private EIRC eirc;
 	private String title;
 	private MircSmileyTextArea text_canvas;
 	private TextField new_chan, users_nbr;
 	private Checkbox byname, bynumber;	
 	private ImageButton b;
 //	private BorderedPanel panel;
 	private Label label;
 	private int number = 0;
 
 	private Resources res;
 	protected static final String min_str = Resources.getString("channel_list.minima");
 	protected static final String users_str = Resources.getString("channel_list.users");
 	protected static final String newchan_str = Resources.getString("channel_list.new");
 	protected static final String refresh = Resources.getString("channel_list.refresh");
 	
 	private Vector chans;
 	private Vector chanserv;
 	private Collator collator;
 	
 	private final int SORT_BYNAME = 0;
 	private final int SORT_BYNUM = 1;
 	private final int SORT_BYTOPIC = 2;
 	
 	private int sort_criteria = SORT_BYNAME;
 	
 	/* Configuration properties. */
 	private String list_parameter;
 
 
 	public ChanListWindow(EIRC eirc, String title)
 	{
 		super(title);
 		text_canvas = new MircSmileyTextArea(this, this);
 
 		this.eirc = eirc;
 		this.title = title;
 		this.collator = Collator.getInstance();
 		
 		text_canvas.setMode(eirc.scrollSpeed());
 		text_canvas.setBufferlen(35000);
 		text_canvas.setBreaks(false);
 		int tabs[] = {-1, 160, 190};
 		text_canvas.setTabs(tabs);
 		
 		GridBagLayout gb = new GridBagLayout();
 		GridBagConstraints gbc = new GridBagConstraints();
 		setLayout(gb);
 
 		gbc.insets = new Insets(2, 2, 2, 2);
 		
 		label = new Label(newchan_str + " : ");
 		gbc.gridx = 0;
 		gbc.gridy = 2;
 		gbc.gridwidth = 3;
 		gbc.anchor = GridBagConstraints.WEST;
 		gbc.fill = GridBagConstraints.NONE;
 		gbc.weighty = 0;
 	  	gbc.weightx = 0;
 		gb.setConstraints(label, gbc);
 		add(label);
 
 		new_chan = new TextField(20);
 		gbc.gridx = 3;
 		gbc.weighty = 0;
 		gbc.gridwidth = 4;
 		gbc.anchor = GridBagConstraints.WEST;
 		gbc.fill = GridBagConstraints.HORIZONTAL;
 		gb.setConstraints(new_chan, gbc);
 		add(new_chan);
 		
 //		panel = new BorderedPanel(res.getString("channel_list.frame"));
 //		GridBagLayout gb2 = new GridBagLayout();
 //		GridBagConstraints gbc2 = new GridBagConstraints();
 //		panel.setLayout(gb2);
 
 //		gbc2.weightx = 1.0;
 //		gbc2.insets = new Insets(2, 2, 2, 2);
 		
 		Label l = new Label(min_str);
 		gbc.gridx = 0;
 		gbc.gridy = 0;
 		gbc.gridwidth = 1;
 		gbc.weightx = 0;
 		gbc.fill = GridBagConstraints.NONE;
 		gbc.anchor = GridBagConstraints.WEST;
 		gb.setConstraints(l, gbc);
 		add(l);
 		
 		gbc.gridx++;
 		
 		users_nbr = new TextField("1", 2);
 		gb.setConstraints(users_nbr, gbc);
 		add(users_nbr);
 		
 		gbc.gridx++;
 		
 		l = new Label(users_str);
 		gb.setConstraints(l, gbc);
 		add(l);
 		
 		l = new Label(res.getString("channel_list.sort") + " :");
 		gbc.gridx++;
 		gb.setConstraints(l, gbc);
 		add(l);
 
 		CheckboxGroup cbg = new CheckboxGroup();
 		byname = new Checkbox(res.getString("channel_list.byname"), cbg, (sort_criteria == SORT_BYNAME));
 		gbc.gridx++;
 	   	gb.setConstraints(byname, gbc);
 		add(byname);
 		
 		bynumber = new Checkbox(res.getString("channel_list.bynumber"), cbg, (sort_criteria == SORT_BYNUM));
 		gbc.gridx++;
 		gb.setConstraints(bynumber, gbc);
 		add(bynumber);
 		
 		b = new ImageButton(refresh);
 		b.setWaitType();
 		b.setEnabled(true);
 		b.setActionCommand("list");
 		gbc.gridx++;
 		gbc.anchor = GridBagConstraints.WEST;
 		gb.setConstraints(b, gbc);
 		add(b);
 
 //		gbc.gridx = 0;
 //		gbc.gridy++;
 //		gbc.gridwidth = 2;
 //		gbc.weighty = 0;
 //		gbc.anchor = GridBagConstraints.NORTH;
 //		gb.setConstraints(panel, gbc);
 //		add(panel);
 		
 		
 		gbc.gridx = 0;
 		gbc.gridy = 1;
 		gbc.anchor = GridBagConstraints.CENTER;
 		gbc.fill = GridBagConstraints.BOTH;
 		gbc.weighty = 1;
 	  	gbc.weightx = 1;
 	  	gbc.gridwidth = 7;
 		gb.setConstraints(text_canvas, gbc);
 		add(text_canvas);
 
 		bynumber.addItemListener(this);
 		byname.addItemListener(this);
 		new_chan.addActionListener(this);
 		users_nbr.addActionListener(this);
 		b.addActionListener(this);
 
 //		readChanServList("chanlist.txt");
 	}
 
 	public void clear()
 	{
 		text_canvas.clear();
 	}
 	
 	public void listChannels()
 	{
 		String l[];
 		int min = 1;
 		try
 		{
 			min = Integer.parseInt(users_nbr.getText());
 		} catch (NumberFormatException e) {}
 		
 		if (--min > 0)
 		{
 			l = new String[1];
 			l[0] = MessageFormat.format(list_parameter, new Object[] { new Integer(min) });
 			eirc.sendMessage("LIST", l);
 		}
 		else
 		{
 			l = new String[0];
 			eirc.sendMessage("LIST", l);
 		}
 	}
 	
 	public void loadChannels(Vector data)
 	{
 /*
 		for (Enumeration e = chanserv.elements(); e.hasMoreElements(); )
 		{
 			ChannelItem reg_channel = (ChannelItem) e.nextElement();
 			String reg_name = reg_channel.getTag();
 			
 			boolean insert = true;
 			for (Enumeration ee = data.elements(); ee.hasMoreElements(); )
 			{
 				ChannelItem channel = (ChannelItem) ee.nextElement();
 				String name = channel.getTag();
 				if (reg_name.equalsIgnoreCase(name))
 					insert = false;
 			}
 			if (insert)
 				data.addElement(reg_channel);
 		}
 */
 		this.chans = data;
 		display();
 	}
 
 	private void display()
 	{
 		text_canvas.setMode(text_canvas.SAFE);
 		text_canvas.clear();
 
 		sort(chans);
 
 	  	for (Enumeration e = chans.elements(); e.hasMoreElements(); )
 	  	{
 			ChannelItem channel = (ChannelItem) e.nextElement();
 			String topic = channel.getTopic();
 						
 			if (topic != null)
 			{
 				// Strip chan modes in topic (Unreal)
 				
 				if (topic.startsWith("[+"))
 				{
 					MessageFormat mf = new MessageFormat("[+{0}] {1}");
 					try
 					{
 						Object o[] = mf.parse(topic);
 						if (o[1] != null)
 							topic = o[1].toString();
 					}
 					catch (ParseException ex) {}
 				}					
 			 }  
 			text_canvas.append(channel.getTag() + " " + MircMessage.COLOR + "3 " + channel.getUsers() + " " + MircMessage.RESET + topic);
 		}
 
 		text_canvas.setMode(eirc.scrollSpeed());
 		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;
 		ChannelItem a = (ChannelItem)o1;
 		ChannelItem b = (ChannelItem)o2;
 		
 		switch (sort_criteria)
 		{
 		default:
 		case SORT_BYNAME:
 			comp = collator.compare(a.getTag(), b.getTag());
 			break;
 		case SORT_BYNUM:
 			comp = b.getUsers() - a.getUsers();
 			break;
 		case SORT_BYTOPIC:
 			comp = collator.compare(a.getTopic(), b.getTopic());
 			break;
 		}
 		return(comp);
 	}
 		
 	public int number()
 	{
 		return(number);
 	}
 /*
 	private void readChanServList(String f)
 	{
 		this.chanserv = new Vector();
 		URL u = null;
 		try
 		{
 			u = new URL(eirc.getCodeBase() + f);
 		}
 		catch(MalformedURLException e)
 		{
 			u = ClassLoader.getSystemResource(f);
 		}
 
 		try
 		{
 			BufferedReader br = new BufferedReader(new InputStreamReader(u.openStream()));
 			String s;
 			while((s = br.readLine()) != null)
 			{
    				MessageFormat m = new MessageFormat("{0}\t{1}");
    				try
    				{
    					Object ob[] = m.parse(s);
    					if (ob[0] != null)
    					{
    						chanserv.addElement(new ChannelItem((String)ob[0], 0, (String)ob[1]));
    						number_reg++;
    					}
    				}
    				catch (ParseException ex) {}
 			}
 			br.close();
 		}
 		catch(IOException e)
 		{
 			System.out.println("Cannot open " + u);
 		}
 	}
 */
 	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);
 		label.setBackground(c);
 //		updateBackground((Container)panel, c);
 	}
 
 	public void setTextBackground(Color c)
 	{
 		new_chan.setBackground(c);
 		users_nbr.setBackground(c);
 		text_canvas.setBackground(c);
 	}
 	
 	public void setSelectedBackground(Color c)
 	{
 		text_canvas.setSelectedBackground(c);
 	}
 
 	public void setForeground(Color c)
 	{
 		super.setForeground(c);
 	}
 
 	public void setTextForeground(Color c)
 	{
 		new_chan.setForeground(c);
 		users_nbr.setForeground(c);
 	}
 
 	public void setFont(Font f)
 	{
 		new_chan.setFont(f);
 		users_nbr.setFont(f);
 		text_canvas.setFont(f);
 	}
 
 	protected void visitURL(URL url)
 	{
 		eirc.visitURL(url);
 	}
 
 	protected void joinChannel(String name)
 	{
 		eirc.joinChannel(name);
 	}
 	
 	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)
 	{
 	}
 
 	public void addText(String s)
 	{
 		eirc.cutPaste(s);
 	}
 
 	public void update(Observable o, Object arg)
 	{
 		ConfigurationProperties props = (ConfigurationProperties) o;
 
  		if (arg == null || arg.equals("list_parameter"))
 			this.list_parameter = props.getString("list_parameter");
 			
 		if (arg == null || arg.equals("scroll_speed"))
 			text_canvas.setMode(props.getInt("scroll_speed"));
 	}
 
 	public void itemStateChanged(ItemEvent ev) 
 	{
 		Object ob = ev.getSource();
 		if (ob == byname || ob == bynumber)
 		{
 			if (byname.getState())
 				sort_criteria = SORT_BYNAME;
 			if (bynumber.getState())
 				sort_criteria = SORT_BYNUM;
 				
 			display();
 		}
 	}
 	
 	public void actionPerformed(ActionEvent ev)
 	{
 		String ac = ev.getActionCommand();
 		Object ob = ev.getSource();
 
 		if (ob == new_chan)
 		{
 			String chan = new_chan.getText();
 			if (!Channel.isChannel(chan))
 				chan = "#" + chan;
 			
 			if (chan.length() > 1)
 				joinChannel(chan);
 		}
 		
 		if (ac.equals("list") || ob == users_nbr)
 		{
 			b.setEnabled(false);
 			
 			listChannels();
 		}
 	}
 }