package cn.wisenergy.common.utils;

import com.alibaba.druid.util.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class DateUtil {

	public static final String[] YEAR_MONTHS = new String[]{"01", "02", "03",
			"04", "05", "06", "07", "08", "09", "10", "11", "12"};

	public static final String[] CHINA_MONTHS = new String[]{"一月", "二月",
			"三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"};

	public static final String[] DAY_HOURS = new String[]{"00", "01", "02",
			"03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13",
			"14", "15", "16", "17", "18", "19", "20", "21", "22", "23"};

	public static final String[] MONTH_DAYS = new String[]{"01", "02", "03",
			"04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14",
			"15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25",
			"26", "27", "28", "29", "30", "31"};

	/**
	 * 生成多层日期目录
	 *
	 * @param level 目录层数(最多3层)即:月(200906)-日(0605)-时(01)
	 * @return
	 */
	public static String generateDateDir(int level) {
		if (level < 1 || level > 5) {
			level = 3;// 默认3
		}
		SimpleDateFormat levelOne = new SimpleDateFormat("yyyyMM");
		SimpleDateFormat levelTwo = new SimpleDateFormat("MMdd");
		SimpleDateFormat levelThree = new SimpleDateFormat("HH");
		SimpleDateFormat levelFour = new SimpleDateFormat("yyyy-MM-dd");

		String s = "/";
		String destDirectory = "";
		Date date = new Date(System.currentTimeMillis());

		switch (level) {
			case 1:
				destDirectory += levelOne.format(date);
				break;
			case 2:
				destDirectory += levelOne.format(date) + s + levelTwo.format(date);
				break;
			case 3:
				destDirectory += levelOne.format(date) + s + levelTwo.format(date)
						+ s + levelThree.format(date);
				break;
			case 4:
				destDirectory = levelFour.format(date);
				break;
			case 5:
				destDirectory = levelFour.format(getYesterday());
				break;
		}
		return destDirectory;
	}

	/**
	 * 获取年
	 *
	 * @param date
	 * @return
	 */
	public static int getYear(Date date) {
		return getValue(date, Calendar.YEAR);
	}

	/**
	 * 获取月
	 *
	 * @param date
	 * @return
	 */
	public static int getMonth(Date date) {
		return getValue(date, Calendar.MONTH);
	}

	/**
	 * 获取星期
	 *
	 * @param date
	 * @return
	 */
	public static int getWeek(Date date) {
		return getValue(date, Calendar.DAY_OF_WEEK);
	}

	/**
	 * 获取日
	 *
	 * @param date
	 * @return
	 */
	public static int getDay(Date date) {
		return getValue(date, Calendar.DAY_OF_MONTH);
	}

	/**
	 * 获取小时
	 *
	 * @param date
	 * @return
	 */
	public static int getHour(Date date) {
		return getValue(date, Calendar.HOUR_OF_DAY);
	}

	/**
	 * 获取分钟
	 *
	 * @param date
	 * @return
	 */
	public static int getMinute(Date date) {
		return getValue(date, Calendar.MINUTE);
	}

	/**
	 * 获取分钟
	 *
	 * @param date
	 * @return
	 */
	public static int getSecond(Date date) {
		return getValue(date, Calendar.SECOND);
	}

	/**
	 * @param date
	 * @param field
	 * @return
	 */
	private static int getValue(Date date, int field) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(date.getTime());
		return calendar.get(field);
	}

	/**
	 * 解析日期
	 *
	 * @param strDate
	 * @return
	 * @throws ParseException
	 */
	public static Date convertStrToDate(String strDate, String pattern) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(pattern);
			return sdf.parse(strDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 字符串转calendar
	 *
	 * @param date    日期的字符串
	 * @param pattern 日期的格式
	 * @return
	 */
	public static Calendar convertStrToCalendar(String date, String pattern) {
		Calendar calendar = null;
		try {
			calendar = Calendar.getInstance();
			SimpleDateFormat format = new SimpleDateFormat(pattern);
			calendar.setTime(format.parse(date));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return calendar;
	}

	/**
	 * 格式化date为指定的格式字符串
	 *
	 * @param date
	 * @param pattern
	 * @return
	 */
	public static String convertDateToStr(Date date, String pattern) {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	/**
	 * 转换日期为字符串
	 *
	 * @param date
	 * @return
	 */
	public static String convertDateToYMDStr(Date date) {
		if (date == null) {
			return null;
		}
		return new SimpleDateFormat("yyyy-MM-dd").format(date);
	}

	/**
	 * 给日期增加值
	 *
	 * @param date
	 * @param field
	 * @param amount
	 * @return
	 */
	public static Date add(Date date, int field, int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(date.getTime());
		calendar.add(field, amount);
		return new Date(calendar.getTimeInMillis());
	}

	/**
	 * 取上个月的第一天
	 */
	public static Calendar getLastMonFirstDay(Calendar calendar) {
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH);
		if (month > 0) {
			month--;
		} else {
			year--;
			month = 11;
		}
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, month);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		return calendar;
	}

	/**
	 * 取上个月的最后一天
	 */
	public static Calendar getLastMonLastDay(Calendar calendar) {
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return calendar;
	}

	/**
	 * 取得上一天
	 */
	public static Calendar getLastDay(Calendar calendar) {
		calendar.add(Calendar.DAY_OF_YEAR, -1);
		return calendar;
	}

	/**
	 * 取上个周的最后一天
	 */
	public static Calendar getLastweekLastDay(Calendar calendar) {
		calendar.add(Calendar.SUNDAY, -7);
		return calendar;
	}

	/**
	 * 取一天中最大时间 毫秒为999
	 *
	 * @param day
	 * @return
	 * @throws ParseException
	 */
	public static Date getEndOfDay(Date day) {

		if (day == null) {
			day = new Date();
		}

		Calendar cal = Calendar.getInstance();
		cal.setTime(day);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE));
		cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));

		return cal.getTime();
	}

	/**
	 * 取一天中最大时间 毫秒为0
	 *
	 * @param day
	 * @return
	 * @throws ParseException
	 */
	public static Date getEndZeroMillOfDay(Date day) {

		if (day == null) {
			day = new Date();
		}

		Calendar cal = Calendar.getInstance();
		cal.setTime(day);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE));
		cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, 0);

		return cal.getTime();
	}

	/**
	 * 取一天中最小时间
	 *
	 * @param day
	 * @return
	 * @throws ParseException
	 */
	public static Date getStartOfDay(Date day) {

		if (day == null) {
			day = new Date();
		}

		Calendar cal = Calendar.getInstance();
		cal.setTime(day);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE));
		cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));

		return cal.getTime();
	}

	/**
	 * 取今天的最小时间
	 *
	 * @return
	 * @throws ParseException
	 */
	public static Date getTodayStart() {
		return getStartOfDay(new Date());
	}

	/**
	 * 计算两个日期之间相差的天数
	 *
	 * @param startDate 较小的时间
	 * @param endDate   较大的时间
	 * @return 相差天数
	 */
	public static int daysBetween(Date startDate, Date endDate) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(startDate);
		long time1 = cal.getTimeInMillis();
		cal.setTime(endDate);
		long time2 = cal.getTimeInMillis();
		long betweenDays = (time2 - time1) / (1000 * 3600 * 24);
		return Integer.parseInt(String.valueOf(betweenDays));
	}

	/**
	 * 获取当前月份天数的数组
	 *
	 * @return
	 */
	public static String[] getCurrentMonthDaysArray() {
		return getMonthDaysArray(new Date());
	}

	/**
	 * 获取指定月份天数的数组
	 *
	 * @return
	 */
	public static String[] getMonthDaysArray(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
		String[] array = new String[maxDay];
		System.arraycopy(MONTH_DAYS, 0, array, 0, maxDay);
		return array;
	}

	/**
	 * 获取当前月的第一天
	 *
	 * @return
	 */
	public static Date getCurrentFirstDayOfMonth() {
		return getFirstDayOfMonth(new Date());
	}

	/**
	 * 获取当前月的
	 *
	 * @return
	 */
	public static Date getCurrentLastDayOfMonth() {
		return getLastDayOfMonth(new Date());
	}

	/**
	 * 获取指定时间中月的第一天
	 *
	 * @return
	 */
	public static Date getFirstDayOfMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取指定时间中月的
	 *
	 * @return
	 */
	public static Date getLastDayOfMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_MONTH,
				calendar.getMaximum(Calendar.DAY_OF_MONTH));
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTime();
	}

	/**
	 * 获取当前年的第一天
	 *
	 * @return
	 */
	public static Date getCurrentFirstDayOfYear() {
		return getFirstDayOfYear(new Date());
	}

	/**
	 * 获取指定年份的第一天
	 *
	 * @return
	 */
	public static Date getFirstDayOfYear(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_YEAR, 1);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取昨天时间
	 *
	 * @return
	 */
	public static Date getYesterday() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -1);
		return cal.getTime();
	}

	public/**
	 * 获取今天
	 */
	static Date getToday() {
		Calendar cal = Calendar.getInstance();
		return cal.getTime();
	}

	/**
	 * 获取前一天
	 *
	 * @return
	 */
	public static Date getYesterday(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE, -1);
		return cal.getTime();
	}

	/**
	 * 获取后一天
	 *
	 * @return
	 */
	public static Date getTomorrow(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE, 1);
		return cal.getTime();
	}

	/**
	 * 获取前一个月
	 *
	 * @return
	 */
	public static Date getLastMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, -1);
		return cal.getTime();
	}

	/**
	 * 获取后一个月
	 *
	 * @return
	 */
	public static Date getNextMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, 1);
		return cal.getTime();
	}

	/**
	 * 获取大写的月份
	 *
	 * @param date
	 * @return
	 */
	public static String getChinaMonth(Date date) {
		Calendar instance = Calendar.getInstance();
		instance.setTime(date);
		return CHINA_MONTHS[instance.get(Calendar.MONTH)];
	}

	/**
	 * 比较两个时间的时分
	 *
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static int compareToHourMin(Date date1, Date date2) {
		Calendar calendar1 = Calendar.getInstance();
		calendar1.setTime(date1);
		calendar1.set(Calendar.SECOND, 0);

		Calendar temp = Calendar.getInstance();
		temp.setTime(date2);

		Calendar calendar2 = (Calendar) calendar1.clone();
		calendar2.set(Calendar.HOUR_OF_DAY, temp.get(Calendar.HOUR_OF_DAY));
		calendar2.set(Calendar.MINUTE, temp.get(Calendar.MINUTE));
		calendar2.set(Calendar.SECOND, 0);

		return calendar1.compareTo(calendar2);
	}

	/**
	 * 计算两个日期是否是一周(周一作为一周的开始时间)
	 *
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static boolean isSameWeek(Date date1, Date date2) {

		Calendar calendar1 = Calendar.getInstance();
		calendar1.setTime(date1);
		calendar1.setFirstDayOfWeek(Calendar.MONDAY);

		Calendar calendar2 = Calendar.getInstance();
		calendar2.setTime(date2);
		calendar2.setFirstDayOfWeek(Calendar.MONDAY);

		if (calendar1.get(Calendar.WEEK_OF_YEAR) == calendar2
				.get(Calendar.WEEK_OF_YEAR)) {
			return true;
		}

		return false;
	}

	/**
	 * 根据开始时间和结束时间返回时间段内的时间集合
	 *
	 * @param startDate
	 * @param endDate
	 * @return List
	 */
	public static List<Date> getDatesBetweenTwoDate(Date startDate, Date endDate) {
		List<Date> dates = new ArrayList<Date>();
		dates.add(startDate);// 把开始时间加入集合
		Calendar cal = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		cal.setTime(startDate);
		while (true) {
			cal.add(Calendar.DAY_OF_MONTH, 1);
			if (endDate.after(cal.getTime())
					&& !DateUtils.isSameDay(endDate, cal.getTime())) {
				dates.add(cal.getTime());
			} else {
				break;
			}
		}
		if (startDate.compareTo(endDate) != 0) {
			dates.add(endDate);// 把结束时间加入集合
		}
		return dates;
	}

	/**
	 * 获取时间段内的时间字符串集合
	 *
	 * @param startDate
	 * @param endDate
	 * @param dateFormat
	 * @return
	 */
	public static List<String> getDateCollection(Date startDate, Date endDate,
												 String dateFormat) {

		if (dateFormat == null || StringUtils.equals(dateFormat, "")) {
			dateFormat = "yyyy-MM-dd";
		}
		List<String> dates = new ArrayList<String>();
		dates.add(DateUtil.convertDateToStr(startDate, dateFormat));
		Calendar cal = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		cal.setTime(startDate);
		while (true) {
			cal.add(Calendar.DAY_OF_MONTH, 1);
			if (endDate.after(cal.getTime())
					&& !DateUtils.isSameDay(endDate, cal.getTime())) {
				dates.add(DateUtil.convertDateToStr(cal.getTime(), dateFormat));
			} else {
				break;
			}
		}
		dates.add(DateUtil.convertDateToStr(endDate, dateFormat));// 把结束时间加入集合
		return dates;
	}

	/**
	 * 获得某个月的日期表格
	 *
	 * @param month
	 * @return List
	 */
	public static List<Date> getDateTab(Date month) {
		Date startDate = getFirstDayOfMonth(month);
		Date endDate = getLastDayOfMonth(month);
		Calendar cal1 = Calendar.getInstance();
		Calendar cal2 = Calendar.getInstance();
		cal1.setTime(startDate);
		cal2.setTime(endDate);
		int i = cal1.get(Calendar.DAY_OF_WEEK);
		int j = cal2.get(Calendar.DAY_OF_WEEK);
		cal1.add(Calendar.DAY_OF_MONTH, -i + 1);
		cal2.add(Calendar.DAY_OF_MONTH, 7 - j);
		Date beforeDate = cal1.getTime();
		Date afterDate = cal2.getTime();
		return getDatesBetweenTwoDate(beforeDate, afterDate);
	}

	/**
	 * 转化大写的月份（一月……十二月）为数字月份（01……12）
	 *
	 * @param chinaMonthName
	 * @return
	 */
	public static String convertMonthToNum(String chinaMonthName) {
		int i = ArrayUtils.indexOf(CHINA_MONTHS, chinaMonthName);
		return i > -1 ? YEAR_MONTHS[i] : "";
	}

	/**
	 * 将两个时间根据指定天数分割为多个时间段
	 *
	 * @param startDate 开始时间
	 * @param endDate   结束时间
	 * @param fate      每个时间段间隔的天数
	 * @return 分割后的时间段:[[开始时间,结束时间],[开始时间,结束时间],...]
	 */
	public static List<Date[]> toTimeSlot(Date startDate, Date endDate,
										  Integer fate) {
		if (startDate == null || endDate == null) {
			/* 开始时间或结束时间为空返回空集合 */
			return new ArrayList<Date[]>();
		}
		List<Date[]> result = new ArrayList<Date[]>();
		/* 间隔天 */
		List<Date> days = getDatesBetweenTwoDate(startDate, endDate);
		/* 总天数 */
		Integer dayNumber = days.size();
		if (dayNumber < fate) {
			/* 如果间隔天数大于总天数则直接返回开始时间和结束时间 */
			result.add(new Date[]{startDate, endDate});
		} else {
			/* 时间段个数 */
			Integer size = dayNumber / fate;
			/* 余数 */
			Integer remain = dayNumber % fate;
			if (remain > 0) {
				/* 余数大于零则将时间段个数加一 */
				size += 1;
			} else {
				/* 否则则将余数设置为间隔天数 */
				remain = fate;
			}
			/* 计算时间段 */
			for (int i = 1; i <= size; i++) {
				Integer start = i - 1;
				/* 时间段开始时间所在的索引 */
				Integer startIndex = start * fate;// +(start==0?0:1);
				/* 时间段结束时间所在的索引 */
				Integer endIndex = startIndex + fate;
				if (i == size) {
					endIndex = startIndex + (remain - 1);
				}
				result.add(new Date[]{days.get(startIndex),
						days.get(endIndex - (start == 0 ? 1 : 0)) // 如果当前是第一次遍历结束时间索引减一
				});
			}
		}
		return result;
	}

	/**
	 * 获取指定时间的时间戳【毫秒】
	 *
	 * @param date
	 * @return
	 */
	public static Long getTime(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.getTimeInMillis();
	}

	/**
	 * 根据字符串获取date
	 */
	public static Date getTime(String date, String format) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(format);
		try {
			return dateFormat.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static String getTime(Date date, String format) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(format);
		return dateFormat.format(date);
	}

	/**
	 * 计算两个时间相差时间，格式 *天*小时*分钟*秒
	 */
	public static String getDatePoor(Date endDate, Date nowDate) {

		long nd = 1000 * 24 * 60 * 60;
		long nh = 1000 * 60 * 60;
		long nm = 1000 * 60;
		long ns = 1000;
		// 获得两个时间的毫秒时间差异
		long diff = endDate.getTime() - nowDate.getTime();
		// 计算差多少天
		long day = diff / nd;
		// 计算差多少小时
		long hour = diff % nd / nh;
		// 计算差多少分钟
		long min = diff % nd % nh / nm;
		// 计算差多少秒//输出结果
		long sec = diff % nd % nh % nm / ns;
		return day + "天" + hour + "小时" + min + "分钟" + sec + "秒";
	}

	/**
	 * 计算两个时间相差多少分钟
	 */
	public static Long getDateDifferenceMinute(Date endDate, Date nowDate) {


		long nm = 1000 * 60;
		// 获得两个时间的毫秒时间差异
		long diff = endDate.getTime() - nowDate.getTime();
		// 计算差多少分钟
		long min = diff / nm;

		return min;
	}
}
