/*******************************************************************************
 * Copyright (c) 2010 Robert "Unlogic" Olofsson (unlogic@unlogic.se).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v3
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-3.0-standalone.html
 ******************************************************************************/
package se.unlogic.standardutils.numbers;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

public class NumberUtils {

   private static final Pattern NUMBER_PATTERN = Pattern.compile("\\D*");

   public static boolean isLong(Double value) {

      if (value != null) {

         Long longValue = value.longValue();
         Double doubleValue = longValue.doubleValue();

         if (doubleValue.equals(value)) {
            return true;
         }
      }
      return false;
   }

   public static boolean isInt(String value) {

      if (value != null) {

         try {
            Integer.parseInt(value);
            return true;

         } catch (NumberFormatException e) {}
      }
      return false;
   }

   public static boolean isLong(String value) {

      if (value != null) {

         try {
            Long.parseLong(value);
            return true;

         } catch (NumberFormatException e) {}
      }
      return false;
   }

   public static boolean isFloat(String value) {

      if (value != null) {

         try {
            Float.parseFloat(value);
            return true;

         } catch (NumberFormatException e) {}
      }
      return false;
   }

   public static boolean isDouble(String value) {

      if (value != null) {
         try {
            Double.parseDouble(value);
            return true;

         } catch (NumberFormatException e) {}
      }
      return false;
   }

   public static boolean isNumber(String value) {

      return isDouble(value) || isLong(value) ? true : false;
   }

   public static Integer toInt(String value) {

      if (value != null) {
         try {
            return Integer.parseInt(value);

         } catch (NumberFormatException e) {}
      }

      return null;
   }

   public static List<Integer> toInt(Collection<? extends Object> list, Field field) throws IllegalArgumentException, IllegalAccessException {

      Type type = field.getType();

      if (list != null && type.equals(Integer.class) || type.equals(int.class)) {

         List<Integer> validIntegers = new ArrayList<Integer>();

         for (Object object : list) {

            Integer value = (Integer) field.get(object);

            if (value != null) {
               validIntegers.add(value);
            }

         }

         return validIntegers;
      }

      return null;

   }

   public static ArrayList<Integer> toInt(Collection<String> values) {

      if (values == null) {

         return null;

      } else {

         ArrayList<Integer> validIntegers = new ArrayList<Integer>();

         for (String value : values) {

            if (value != null) {

               Integer intValue = NumberUtils.toInt(value);

               if (intValue != null) {
                  validIntegers.add(intValue);
               }
            }
         }

         if (validIntegers.isEmpty()) {

            return null;

         } else {

            return validIntegers;
         }
      }
   }

   public static ArrayList<Integer> toInt(String[] values) {

      if (values == null) {

         return null;

      } else {

         ArrayList<Integer> validIntegers = new ArrayList<Integer>();

         for (String value : values) {

            if (value != null) {

               Integer intValue = NumberUtils.toInt(value);

               if (intValue != null) {
                  validIntegers.add(intValue);
               }
            }
         }

         if (validIntegers.isEmpty()) {

            return null;

         } else {

            return validIntegers;
         }
      }
   }

   public static Long toLong(String value) {

      if (value != null) {
         try {
            return Long.parseLong(value);
         } catch (NumberFormatException e) {}
      }

      return null;
   }

   public static Float toFloat(String value) {

      if (value != null) {
         try {
            return Float.parseFloat(value);
         } catch (NumberFormatException e) {}
      }

      return null;
   }

   public static Double toDouble(String value) {

      if (value != null) {
         try {
            return Double.parseDouble(value);
         } catch (NumberFormatException e) {}
      }

      return null;
   }

   public static List<Double> toDouble(List<String> values) {

      if (values == null) {

         return null;

      } else {

         ArrayList<Double> validDoubles = new ArrayList<Double>();

         for (String value : values) {

            if (value != null) {

               Double doubleValue = NumberUtils.toDouble(value);

               if (doubleValue != null) {
                  validDoubles.add(doubleValue);
               }
            }
         }

         if (validDoubles.isEmpty()) {
            return null;
         } else {
            return validDoubles;
         }
      }
   }

   public static List<Long> toLong(List<String> values) {

      if (values == null) {
         return null;
      } else {
         ArrayList<Long> validLongs = new ArrayList<Long>();

         for (String value : values) {
            if (value != null) {
               Long LongValue = NumberUtils.toLong(value);

               if (LongValue != null) {
                  validLongs.add(LongValue);
               }
            }
         }

         if (validLongs.isEmpty()) {
            return null;
         } else {
            return validLongs;
         }
      }
   }

   public static Long getNumbers(String revstring) {

      String result = NUMBER_PATTERN.matcher(revstring).replaceAll("");

      return toLong(result);
   }

   public static String formatNumber(Number value, int minDecimals, int maxDecimals, boolean grouping, boolean dotDecimalSymbol) {

      DecimalFormat formatter = new DecimalFormat();

      formatter.setMinimumFractionDigits(minDecimals);

      formatter.setMaximumFractionDigits(maxDecimals);

      if (dotDecimalSymbol) {

         formatter.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));

      }

      formatter.setGroupingUsed(grouping);

      return formatter.format(value);

   }

   public static Byte toByte(String value) {

      if (value != null) {
         try {
            return Byte.parseByte(value);
         } catch (NumberFormatException e) {}
      }

      return null;
   }

}
