package com.foreverwin.mesnac.common.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.LinkedHashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NumberUtil
{
	public static final double EARTH_RADIUS = 6378.137;
	
	public static final DecimalFormat FORMATTER_DECIMAL = new DecimalFormat("0.00");
	public static final DecimalFormat FORMATTER_DECIMAL_4 = new DecimalFormat("0.0000");
	public static final DecimalFormat FORMATTER_DECIMAL_5 = new DecimalFormat("0.00000");
	public static final DecimalFormat FORMATTER_DECIMAL_7 = new DecimalFormat("0.0000000");
	public static final DecimalFormat FORMATTER_DECIMAL_SHORT = new DecimalFormat("0.0");
	public static final DecimalFormat FORMATTER_DECIMAL_LOCATION = new DecimalFormat("0.000000000000000");
	
    public static double add(Object obj1, Object obj2)
	{
    	return add(obj1, obj2, FORMATTER_DECIMAL);
    }
    
    public static double add(Object obj1, Object obj2, DecimalFormat formatter)
   	{
	    BigDecimal decimal1 = new BigDecimal(toDouble(obj1));
	    BigDecimal decimal2 = new BigDecimal(toDouble(obj2));
	    double result = decimal1.add(decimal2).doubleValue();
	    return Double.valueOf(formatter.format(result)).doubleValue();
   	}
	  
	public static double subtract(Object obj1, Object obj2)
	{
		return subtract(obj1, obj2, FORMATTER_DECIMAL);
	}
	
	public static double subtract(Object obj1, Object obj2, DecimalFormat formatter)
	{
		BigDecimal decimal1 = new BigDecimal(toDouble(obj1));
		BigDecimal decimal2 = new BigDecimal(toDouble(obj2));
		double result = decimal1.subtract(decimal2).doubleValue();
    	return Double.valueOf(formatter.format(result)).doubleValue();
	}
  
	public static double multiply(Object obj1, Object obj2)
	{
		return multiply(obj1, obj2, FORMATTER_DECIMAL);
	}
	
	public static double multiply(Object obj1, Object obj2, DecimalFormat formatter)
	{
		BigDecimal decimal1 = new BigDecimal(toDouble(obj1));
		BigDecimal decimal2 = new BigDecimal(toDouble(obj2));
		double result = decimal1.multiply(decimal2).doubleValue();
		return Double.valueOf(formatter.format(result)).doubleValue();
	}
	
	public static double divide(Object obj1, Object obj2)
	{
		return divide(obj1, obj2, FORMATTER_DECIMAL);
	}
	
	public static double divide(Object obj1, Object obj2, DecimalFormat formatter)
	{
		double result = 0.0D;
		BigDecimal decimal1 = new BigDecimal(toDouble(obj1));
		BigDecimal decimal2 = new BigDecimal(toDouble(obj2));
		if (toDouble(decimal2) > 0.0D) 
		{
			result = decimal1.divide(decimal2, 3, 1).doubleValue();
		}
		return Double.valueOf(formatter.format(result)).doubleValue();
	}

	public static double divide(Object obj1, Object obj2, DecimalFormat formatter, int scale)
	{
		double result = 0.0D;
		BigDecimal decimal1 = new BigDecimal(toDouble(obj1));
		BigDecimal decimal2 = new BigDecimal(toDouble(obj2));
		if (toDouble(decimal2) > 0.0D) 
		{
			result = decimal1.divide(decimal2, scale, 1).doubleValue();
		}
		return Double.valueOf(formatter.format(result)).doubleValue();
	}
	
	public static long round(Object obj)
	{
		BigDecimal decimal = new BigDecimal(toDouble(obj));
		return decimal.setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
	}
	
	public static double round2(Object obj)
	{
		BigDecimal decimal = new BigDecimal(toDouble(obj));
		return decimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
	}
	
	public static int random(int length)
	{
		double number1 = Math.random();
		if (number1 < 0.1)
		{
			number1 = number1 + 0.1;
		}
		
		int number2 = 1;
		for (int i = 0; i < length; i++) 
		{
			number2 = number2 * 10;
		}
		
		return (int)((number1 * number2));
	}
	
	public static Set<Integer> random(int number, int length)
	{
		int size = length;
		if (length > number) 
		{
			size = number;
		}
		
		Random random = new Random();
		Set<Integer> numbers = new TreeSet<Integer>();
		while (numbers.size() < size)
		{
			numbers.add(Integer.valueOf(random.nextInt(number)));
		}
		return numbers;
	}
	
	public static double random(double minNumber, double maxNumber)
	{
		double randomNumber = new Random().nextDouble() * (maxNumber - minNumber) + minNumber;
		return formatDouble(randomNumber, 2);
	}

	public static String format(BigDecimal value, int decimal) {
    	if (value == null) value = BigDecimal.ZERO;

    	return value.setScale(4, RoundingMode.HALF_UP).toPlainString();
	}
	
	public static double formatDouble(Object obj, int length)
	{
		String formatter = "0.0";
		for (int i = 1; i < length; i++) 
		{
			formatter = formatter + "0";
		}
		
		DecimalFormat decimalFormat = new DecimalFormat(formatter);
		return Double.valueOf(decimalFormat.format(obj)).doubleValue();
	}
	
	public static short toShort(Object obj)
	{
		String str = StringUtil.toString(obj);
		if (!str.equals(""))
		{
			try
			{
				return Short.parseShort(str);
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
		}
		return 0;
	}

	public static int toInt(Object obj)
	{
		String str = StringUtil.toString(obj);
		if (!str.equals(""))
		{
			try
			{
				return Integer.parseInt(str);
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
		}
		return 0;
	}

	public static int toInt1(Object obj)
	{
		String str = StringUtil.toString(obj);
		if (!str.equals(""))
		{
			try
			{
				return Integer.parseInt(str);
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
		}
		return 1;
	}

	public static int toPage(Object obj)
	{
		String str = StringUtil.toString(obj);
		if (!str.equals(""))
		{
			try
			{
				int page = Integer.parseInt(str);
				if (page > 0)
				{
					return page;
				}
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
		}
		return 1;
	}

	public static long toLong(Object obj)
	{
		String str = StringUtil.toString(obj);
		if (!str.equals(""))
		{
			try
			{
				return Long.parseLong(str);
			}
			catch (Exception ex)
			{
				//ex.printStackTrace();
			}
		}
		return 0;
	}

	public static float toFloat(Object obj)
	{
		String str = StringUtil.toString(obj);
		if (!str.equals(""))
		{
			try
			{
				return Float.parseFloat(str);
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
		}
		return 0;
	}

	public static double toDouble(Object obj)
	{
		String str = StringUtil.toString(obj);
		if (!str.equals(""))
		{
			try
			{
				return Double.parseDouble(str);
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
			}
		}
		return 0;
    }

    public static int[] toIntArray(char[] chars) 
    {  
    	int i = 0;  
        int[] numbers = new int[chars.length];  
        for (char _char : chars)
        {  
        	numbers[i++] = Integer.parseInt(String.valueOf(_char));  
        }  
        return numbers;  
    } 
    
	public static boolean inIntArray(int number, String numbers)
	{
		boolean inFlag = false;
		String[] _numbers = numbers.split(",");
		for (String _number : _numbers) 
		{
			if (number == toInt(_number)) 
			{
				inFlag = true;
				break;
			}
		}
		return inFlag;
	}
	
    public static boolean isNumber(String str) 
    {  
    	if (!StringUtil.toString(str).equals(""))
    	{
    		return str.matches("^[0-9]*$");  
    	}
    	return false;
    }

	public static boolean isDouble(String str)
	{
		if (!StringUtil.toString(str).equals(""))
		{
			return str.matches("^[0-9]+(.?[0-9]+)?$");
		}
		return false;
	}
    
	public static String toPlainString(Object number) 
	{
		BigDecimal result = new BigDecimal(FORMATTER_DECIMAL.format(number));
		return result.toPlainString();
	}
    
	public static String toPlainString(double number, DecimalFormat formatter) 
	{
		BigDecimal result = new BigDecimal(formatter.format(number));
		return result.toPlainString();
	}
	
	public static Set<Long> toIds(String str)
	{
	    Set<Long> ids = new LinkedHashSet<Long>();
		String[] elements = str.split(",");
	    for (String element : elements)
	    {
	    	long id = toLong(element);
	    	if (id > 0) 
	    	{
	    		ids.add(id);
	    	}
	    }
	    return ids;
	}
	
	public static int setBit(int value, int index) 
	{
		value |= 0x0001 << index;
		return value;
	}
	
	public static int restBit(int value, int index) 
	{
		value &= ~(0x0001 << index);
		return value;
	}

	public static int getBit(int value, int index) 
	{
		int mark = 0x0001 << index;
		if ((value & mark) != 0) 
		{
			return 1;
		}
		return 0;
	}
	
	public static double getMapDistance(double latitude1, double latitude2, double longitude1, double longitude2) 
	{
		double radLatitude1 = rad(latitude1);  
	    double radLatitude2 = rad(latitude2);  
	    double latitudeGap = radLatitude1 - radLatitude2;  
	    double longitudeGap = rad(longitude1) - rad(longitude2);  
	    
	    double result = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(latitudeGap / 2), 2) + Math.cos(radLatitude1) * Math.cos(radLatitude2) * Math.pow(Math.sin(longitudeGap / 2), 2)));  
	    result = result * EARTH_RADIUS;  
	    result = Math.round(result * 10000D) / 10000D;  
	    result = result * 1000;  
	    return result;  
	}
	
	private static double rad(double number) 
	{  
		return number * Math.PI / 180.0;  
	}

	public static int getIntMax(int length)
	{
		return (int)toLong(length);
	}

	public static long getLongMax(int length)
	{
		String temp = "";
		for (int i = 0; i<length; i++)
		{
			temp = temp + 9;
		}
		return toLong(temp);
	}

	public static boolean isPositiveInteger(String str)
	{
		if (str == null || "".equals(str.trim())) return false;

		Pattern pattern = Pattern.compile("[0-9]*");
		Matcher matcher = pattern.matcher(str);

		return matcher.matches();
	}

	public static void main(String[] args) {

	}
}