package net.sf.jasperreports.engine.util;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
import net.sf.jasperreports.engine.JRRuntimeException;

public class DefaultFormatFactory implements FormatFactory {
  public static final String STANDARD_DATE_FORMAT_DEFAULT = "default";
  
  public static final String STANDARD_DATE_FORMAT_SHORT = "short";
  
  public static final String STANDARD_DATE_FORMAT_MEDIUM = "medium";
  
  public static final String STANDARD_DATE_FORMAT_LONG = "long";
  
  public static final String STANDARD_DATE_FORMAT_FULL = "full";
  
  public static final String STANDARD_DATE_FORMAT_HIDE = "hide";
  
  public static final String STANDARD_DATE_FORMAT_SEPARATOR = ",";
  
  public DateFormat createDateFormat(String pattern, Locale locale, TimeZone tz) {
    DateFormat format;
    int[] dateStyle = null;
    int[] timeStyle = null;
    if (pattern != null && pattern.trim().length() > 0) {
      int sepIdx = pattern.indexOf(",");
      String dateTok = (sepIdx < 0) ? pattern : pattern.substring(0, sepIdx);
      dateStyle = getDateStyle(dateTok);
      if (dateStyle != null)
        if (sepIdx >= 0) {
          String timeTok = pattern.substring(sepIdx + ",".length());
          timeStyle = getDateStyle(timeTok);
        } else {
          timeStyle = dateStyle;
        }  
    } 
    if (dateStyle != null && timeStyle != null) {
      format = getDateFormat(dateStyle, timeStyle, locale);
    } else {
      if (locale == null) {
        format = DateFormat.getDateTimeInstance(3, 3);
      } else {
        format = DateFormat.getDateTimeInstance(3, 3, locale);
      } 
      if (pattern != null && pattern.trim().length() > 0 && format instanceof SimpleDateFormat)
        ((SimpleDateFormat)format).applyPattern(pattern); 
    } 
    if (tz != null)
      format.setTimeZone(tz); 
    return format;
  }
  
  protected static int[] getDateStyle(String pattern) {
    if (pattern.equalsIgnoreCase("default"))
      return new int[] { 2 }; 
    if (pattern.equalsIgnoreCase("short"))
      return new int[] { 3 }; 
    if (pattern.equalsIgnoreCase("medium"))
      return new int[] { 2 }; 
    if (pattern.equalsIgnoreCase("long"))
      return new int[] { 1 }; 
    if (pattern.equalsIgnoreCase("full"))
      return new int[] { 0 }; 
    if (pattern.equalsIgnoreCase("hide"))
      return new int[0]; 
    return null;
  }
  
  protected static DateFormat getDateFormat(int[] dateStyle, int[] timeStyle, Locale locale) {
    if (dateStyle.length == 0) {
      if (timeStyle.length == 0)
        return new SimpleDateFormat(""); 
      return (locale == null) ? DateFormat.getTimeInstance(timeStyle[0]) : DateFormat.getTimeInstance(timeStyle[0], locale);
    } 
    if (timeStyle.length == 0)
      return (locale == null) ? DateFormat.getDateInstance(dateStyle[0]) : DateFormat.getDateInstance(dateStyle[0], locale); 
    return (locale == null) ? DateFormat.getDateTimeInstance(dateStyle[0], timeStyle[0]) : DateFormat.getDateTimeInstance(dateStyle[0], timeStyle[0], locale);
  }
  
  public NumberFormat createNumberFormat(String pattern, Locale locale) {
    NumberFormat format = null;
    if (pattern != null && pattern.trim().length() > 0) {
      if (locale == null) {
        format = NumberFormat.getNumberInstance();
      } else {
        format = NumberFormat.getNumberInstance(locale);
      } 
      if (format instanceof DecimalFormat)
        ((DecimalFormat)format).applyPattern(pattern); 
    } 
    return format;
  }
  
  public static FormatFactory createFormatFactory(String formatFactoryClassName) {
    FormatFactory formatFactory = null;
    if (formatFactoryClassName != null) {
      try {
        Class formatFactoryClass = JRClassLoader.loadClassForName(formatFactoryClassName);
        formatFactory = formatFactoryClass.newInstance();
      } catch (ClassNotFoundException e) {
        throw new JRRuntimeException("Error loading format factory class : " + formatFactoryClassName, e);
      } catch (Exception e) {
        throw new JRRuntimeException("Error creating format factory instance : " + formatFactoryClassName, e);
      } 
    } else {
      formatFactory = new DefaultFormatFactory();
    } 
    return formatFactory;
  }
}
