/*
 * COPYRIGHT (c) 1998-1999 Jan-Henrik Haukeland, http://www.tildeslash.com/
 */

package ts.biff;

import java.util.*;
import java.io.*;
import java.net.*;
import java.awt.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;

import ts.config.*;


/**
 * A collection of tutti-frutti utility methods for tildeslash biff.
 *
 * @author  Jan-Henrik Haukeland &lt;hauk@tildeslash.com&gt;
 * @version $Id: Util.java,v 1.3 2001/08/13 12:48:28 hauk Exp $
 *
 */
public final class Util 
{


  private Util() {}



  /**
   * Beep, FIXME: play a real sound clip instead.
   */
  public static void beep()
  {
    Toolkit.getDefaultToolkit().beep();
  }



  /**
   * Returns a users local controlfile or null if it does not exist.
   * If the file is unreachable or not a regular file(!) throw a 
   * ConfigException with an appropriate error message.
   *
   * @return User local controlfile or null
   * @exception ConfigException On error
   */
  public static File getUserConfigFile() throws ConfigException
  {
    String conf= Constant.USER_CONTROL_FILE;
    File localConfigFile= new File(conf);
    
    if ( ! localConfigFile.exists() )
	return (File)null;

    if ( ! localConfigFile.canRead() ||
	 ! localConfigFile.canWrite() )
    {
      throw new ConfigException("No rw access to local controlfile: "+ conf);
    }

    if ( ! localConfigFile.isFile() )
    {
      throw new ConfigException("Local controlfile: " + conf +
				" is not a regular file(!)");
    }

    return localConfigFile;
  }



  /** 
   * Returns an object array with the same values as the submitted vector
   * @return an Object array that contains the same objects as the vector 
   */
  public static Object[] convertToArray(Vector aVector) 
  {
    if (aVector == null)
	return null;

    Object[] o= new Object[aVector.size()];

    aVector.copyInto(o);

    return o;
  }


  /** 
   * @return a Vector that contains the same objects as the array 
   */
  public static Vector convertToVector(Object[] anArray) 
  {
    if (anArray == null)
	return null;
    
    Vector v= new Vector(anArray.length);
    for (int i=0; i < anArray.length; i++) {
      v.addElement(anArray[i]);
    }
    return v;
  }


  // ----------------------- UI specific methods ------------------------ //


  /** 
   * Hack to set application universal font for every widget.
   * An application will normally override some of these. But this
   * method sets the baselevel. 
   * @param f a Font that will be application universal 
   */
  public static void setUniversalFont(Font f)
  {
    Hashtable h= (Hashtable)UIManager.getDefaults();
    for (Enumeration e= h.keys(); e.hasMoreElements();) {
      String key= (String)e.nextElement();
      if ( key.indexOf(".font") > 0 ) {
	UIManager.put(key,f);
      }
    }
  }





  /**
   * Center a window on the screen
   * @param window A Window
   */
  public static final void center(Window window)
  {
    Dimension d= Toolkit.getDefaultToolkit().getScreenSize();
    Dimension w= window.getSize();
    window.setLocation((d.width - w.width) / 2, (d.height - w.height) / 2);
  }




  /**
   * Returns a TableHeaderUI object with zero Dimension. This
   * object is used for turning off titles in a JTable
   * @return a null size TableHeaderUI object
   */
  public static TableHeaderUI getNullTableHeaderUI()
  {
    return new Size();
  }

  static class Size extends TableHeaderUI {
    public Dimension getPreferredSize(JComponent c) {
      return new Dimension(0,0);
    }
  }



  /**
   * Show an application model dialog with the submitted error message
   * @param msg Error message to display
   */
  public static void showError(String msg)
  {
    showError(null, msg);
  }

  
  /**
   * Show an application model dialog with the submitted error message
   * and with a parent. The method search upward in the component 
   * hierarchy to find the parents frame.
   * @param comp A parent to find the frame for
   * @param msg Error message to display
   */
  public static void showError(Component comp, String msg)
  {
    Object[] options = { "OK" };
    int a= JOptionPane.
	showOptionDialog(comp,
			 msg,
			 "Error",
			 JOptionPane.DEFAULT_OPTION,
			 JOptionPane.ERROR_MESSAGE,
			 null, options, options[0]);
  }



  /**
   * Show TsBiff about-dialog with an animated gif. 
   */
  public static void showAbout()
  {
    Object[] options = { "OK" };
    int a= JOptionPane.
	showOptionDialog(null,
			 Constant.ABOUTMSG,
			 "About tsbiff",
			 JOptionPane.DEFAULT_OPTION,
			 JOptionPane.INFORMATION_MESSAGE,
			 BiffIcon.getImageIcon(), 
			 options, options[0]);
  }



  /**
   * Show an application model dialog with the submitted 
   * information message and a parent component
   * @param comp A parent to find the frame for
   * @param msg Info message to display
   */
  public static void showInfo(Component comp, String msg)
  {
    Object[] options = { "OK" };
    int a= JOptionPane.
	showOptionDialog(comp,
			 msg,
			 "Information",
			 JOptionPane.DEFAULT_OPTION,
			 JOptionPane.INFORMATION_MESSAGE,
			 null, options, options[0]);
  }


  /**
   * Show an application model dialog with the submitted 
   * information message
   * @param msg Info message to display
   */
  public static void showInfo(String msg)
  {
    showInfo(null, msg);
  }



  /**
   * Show a Yes/No dialog with the submitted message
   * if it has already been sent.
   * @param parent parent component to center the dialog over
   * @param title for the dialog
   * @param message to display
   * @return true if user pressed yes
   */
  public static boolean showYesNo(Component comp, String title, String message)
  {
    Object[] options = { "YES", "NO" };
    int a= JOptionPane.
	showOptionDialog(comp,
			 message,
			 title,
			 JOptionPane.DEFAULT_OPTION,
			 JOptionPane.WARNING_MESSAGE,
			 null, options, options[0]);
    if (a==0) return true;
    return false;
  }



  /**
   * Show a Yes/No dialog with the submitted message
   * if it has already been sent.
   * @param title for the dialog
   * @param message to display
   * @return true if user pressed yes
   */
  public static boolean showYesNo(String title, String message)
  {
    return showYesNo(null, title,message);
  }



  /**
   * Set a Title border for a Component, with default margin.
   * The title is placed in a TOP position
   * @param c component
   * @param t a Title
   */
  public static void setTitleBorder(JComponent c, String t)
  {
    Border title=  new  TitledBorder(t);
    Border margin= new EmptyBorder(5,5,5,5);
    c.setBorder(new CompoundBorder(title, margin));
  }



  /**
   * Set margins for a JComponent
   * @param margin the margin will apply to all sides
   */
  public static void setMargin(JComponent comp, int m)
  {
    Border margin= new EmptyBorder(m,m,m,m);
    comp.setBorder(margin);
  }


  
  /**
   * Encode a Color and return a String representation of it.
   * I.e. this method is the oposite of Color.decode()
   * @param c the Color to encode
   * @see  java.awt.Color#decode
   * @return a string representation of a Color suitable for Color.decode()
   *         or an empty string if the given color was null
   */
  public static String colorEncode(Color c)
  {
    return ("0x" + Integer.toHexString(c.getRed())   +
 	           Integer.toHexString(c.getGreen()) +
	           Integer.toHexString(c.getBlue()));
  }




  /**
   * Encode a Font and return a String representation of it.
   * I.e. this method is the oposite of Font.decode()
   * @param f the Font to encode
   * @see  java.awt.Font#decode
   * @return a string representation of a Font suitable for Font.decode()
   *         or an empty string if the given font was null
   */
  public static String fontEncode(Font f)
  {
    String style= null;
    if ( f.isBold() ) style= "bold"; else
    if ( f.isPlain() ) style= "plain"; else
    if ( f.isItalic() ) style= "italic";

    String code= f.getName() + "-" + style + "-" + f.getSize() ;

    return code;
  }


  /**
   * Return a string array with font parts. 
   * @param f the Font to split into parts
   * @return an array of font-parts, name+style+size e.g. [serif,plain,10]
   */
  public static String[] fontParts(Font f)
  {
    String code= fontEncode(f);
    StringTokenizer t= new StringTokenizer(code, "-");
    int size= t.countTokens();
    String a[]= new String[size];
    for (int i= 0; i<size; i++) {
      try {
	a[i]= t.nextToken();
      } catch(NoSuchElementException no) {
	a[i]= "";
      }
    }
    return a;
  }




  
  /**
   * Returns the content of a file in a String
   *
   * @param  filename Name of file to read (including path)
   * @return A string with the content of the file, or null
   *         if for some reason the file could not be loaded.
   */
  public static String slurp(String filename) 
  {
    File f;
    FileReader in= null;
    try {
      f= new File(filename);
      
      if ( ! f.exists() || ! f.isFile() )
          return null;
      
      in= new FileReader(f);
      int size= (int)f.length();
      char[] c= new char[size];
      in.read(c, 0, size);
      in.close();
      return new String(c);
    } catch (Exception e) {
      return null;
    }
    finally {
      try { if ( in != null ) in.close(); } catch (IOException e) {} 
    }
  }


}
