package com.neusoft.smart.pos.framework.utils;

import lombok.val;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalUnit;
import java.util.Date;

/**
 * LocalDateTime工具类
 */
public class LocalDateTimeUtils {

	public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
	public static final String DEFAULT_YEAR_MONTH_FORMAT = "yyyy-MM";
	public static final String CHINESE_DATE_FORMAT = "yyyy年MM月dd日";
	public static final String SIMPLE_DATE_FORMAT = "yyyyMMdd";
	public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
	public static final String SIMPLE_DATETIME_FORMAT = "yyyyMMddHHmmss";
	public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
	public static final String SIMPLE_TIME_FORMAT = "HHmmss";
	public static final String CHINESE_DATETIME_FORMAT = "yyyy年MM月dd日 HH:mm:ss";

	/**
	 * 得到系统当前时间毫秒数
	 */
	public static Long getCurrentTimeStamp() {
		return getTimeStamp(LocalDateTime.now());
	}

	/**
	 * 得到指定时间毫秒数
	 */
	public static Long getTimeStamp(LocalDateTime dateTime) {
		return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
	}

	/**
	 * 得到系统当前日期时间
	 * @return 当前日期时间
	 */
	public static LocalDateTime getNow() {
		return LocalDateTime.now();
	}

	/**
	 * 获取当前时间开始时间
	 * @return 当前日期时间
	 */
	public static LocalDateTime getCurrentDayStart() {
		return getDayStart(getNow());
	}

	/**
	 * 获取当前时间开始时间
	 * @return 当前日期时间
	 */
	public static LocalDateTime getCurrentDayEnd() {
		return getDayEnd(getNow());
	}

	/**
	 * 获取一天开始时间
	 * @return 当前日期时间
	 */
	public static LocalDateTime getDayStart(LocalDateTime localDateTime) {
		return localDateTime.withHour(0)
				.withMinute(0)
				.withSecond(0)
				.withNano(0);
	}

	/**
	 * 获取一天的结束
	 * @param localDateTime
	 * @return
	 */
	public static LocalDateTime getDayEnd(LocalDateTime localDateTime) {
		return localDateTime.withHour(23)
				.withMinute(59)
				.withSecond(59)
				.withNano(999999999);
	}

	/**
	 * 转换LocalDateTime为Date
	 * @return
	 */
	public static Date convertLocalDateTimeToDate(LocalDateTime localDateTime) {
		return new Date(getTimeStamp(localDateTime));
	}

	/**
	 * 转换Date为LocalDateTime
	 * @return
	 */
	public static LocalDateTime convertDateToLocalDateTime(Date date) {
		return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
	}

	/**
	 * 根据传入String得到系统日期时间
	 * @return 当前日期时间
	 */
	public static String convertLocalDateTimeToString(LocalDateTime localDateTime,String pattern) {
		DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
		return df.format(localDateTime);
	}

	/**
	 * 根据传入String得到系统日期时间
	 * @return 当前日期时间
	 */
	public static LocalDateTime convertStringToLocalDateTime(String dateTime,String pattern) {
		DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
		return LocalDateTime.parse(dateTime,df);
	}

	/**
	 * 得到用缺省方式格式化的当前日期及时间
	 * @return 当前日期及时间
	 */
	public static String getDateTime() {
		return getDateTime(DEFAULT_DATETIME_FORMAT);
	}

	/**
	 * 得到系统当前日期及时间，并用指定的方式格式化
	 * @param pattern 显示格式
	 * @return 当前日期及时间
	 */
	public static String getDateTime(String pattern) {
		return getNow().format(DateTimeFormatter.ofPattern(pattern));
	}

	/**
	 * 得到当前年份
	 * @return 当前年份
	 */
	public static Integer getCurrentYear() {
		return getNow().getYear();
	}

	/**
	 * 得到当前月份
	 * @return 当前月份
	 */
	public static Integer getCurrentMonth() {
		//用get得到的月份数比实际的小1，需要加上
		return getNow().getMonthValue();
	}

	/**
	 * 得到当前日
	 * @return 当前日
	 */
	public static int getCurrentDay() {
		return getNow().getDayOfMonth();
	}

	/**
	 * 指定时间追加小时
	 * @param localDateTime
	 * @param amount
	 * @return
	 */
	public static LocalDateTime plusHours(LocalDateTime localDateTime, Long amount) {
		return plus(localDateTime,amount.longValue(), ChronoUnit.HOURS);
	}

	/**
	 * 指定时间追加分
	 * @param localDateTime
	 * @param amount
	 * @return
	 */
	public static LocalDateTime plusMinutes(LocalDateTime localDateTime, Long amount) {
		return plus(localDateTime,amount.longValue(), ChronoUnit.MINUTES);
	}

	/**
	 * 指定时间追加秒
	 * @param localDateTime
	 * @param amount
	 * @return
	 */
	public static LocalDateTime plusSeconds(LocalDateTime localDateTime, Long amount) {
		return plus(localDateTime,amount.longValue(), ChronoUnit.SECONDS);
	}

	/**
	 * 日期加上一个数,根据unit不同加不同值,unit为ChronoUnit
	 * @param localDateTime
	 * @param amount
	 * @param unit
	 * @return
	 */
	public static LocalDateTime plus(LocalDateTime localDateTime,Long amount,TemporalUnit unit) {
		return localDateTime.plus(amount,unit);
	}

	/**
	 * 指定时间减去分
	 * @param localDateTime
	 * @param amount
	 * @return
	 */
	public static LocalDateTime minusMinutes(LocalDateTime localDateTime, Long amount) {
		return minu(localDateTime,amount.longValue(), ChronoUnit.MINUTES);
	}

	/**
	 * 指定时间减去秒
	 * @param localDateTime
	 * @param amount
	 * @return
	 */
	public static LocalDateTime minusSeconds(LocalDateTime localDateTime, Long amount) {
		return minu(localDateTime,amount.longValue(), ChronoUnit.SECONDS);
	}

	/**
	 * 指定时间减去月
	 * @param localDateTime
	 * @param amount
	 * @return
	 */
	public static LocalDateTime minusMonth(LocalDateTime localDateTime, Long amount) {
		return minu(localDateTime,amount.longValue(), ChronoUnit.MONTHS);
	}

	/**
	 * 日期减去一个数,根据unit不同加不同值,unit为ChronoUnit
	 * @param localDateTime
	 * @param amount
	 * @param unit
	 * @return
	 */
	public static LocalDateTime minu(LocalDateTime localDateTime, Long amount, TemporalUnit unit){
		return localDateTime.minus(amount,unit);
	}

	/**
	 * 获取与当前时间的间隔分钟
	 * @param endTime
	 * @return
	 */
	public static Long betweenNowMinutes(LocalDateTime endTime) {
		return betweenMinutes(getNow(), endTime);
	}

	/**
	 * 获取两个日期的间隔分钟
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public static Long betweenMinutes(LocalDateTime startTime, LocalDateTime endTime) {
		return betweenTwoTime(startTime, endTime,ChronoUnit.MINUTES);
	}

	/**
	 * 获取与当前时间的间隔秒数
	 * @param endTime
	 * @return
	 */
	public static Long betweenNowSeconds(LocalDateTime endTime) {
		return betweenSeconds(getNow(), endTime);
	}

	/**
	 * 获取两个日期的间隔秒数
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public static Long betweenSeconds(LocalDateTime startTime, LocalDateTime endTime) {
		return betweenTwoTime(startTime, endTime,ChronoUnit.SECONDS);
	}

	/**
	 * 获取两个日期的差  field参数为ChronoUnit.*
	 * @param startTime
	 * @param endTime
	 * @param unit  单位(年月日时分秒)
	 * @return
	 */
	public static Long betweenTwoTime(LocalDateTime startTime, LocalDateTime endTime, ChronoUnit unit) {
		return unit.between(startTime, endTime);
	}

	/**
	 * 获取当前季度索引
	 * @return 1:第一季度 2:第二季度 3:第三季度 4:第四季度
	 */
	public static Integer getCurrentQuarter(){
		return getQuarterOfMonth(getNow());
	}

	/**
	 * 获取指定时间季度索引
	 * @param localDateTime
	 * @return 1:第一季度 2:第二季度 3:第三季度 4:第四季度
	 */
	public static Integer getQuarterOfMonth(LocalDateTime localDateTime){
		Integer month = localDateTime.getMonthValue();
		return month/4+1;
	}

	/**
	 * 取得季度已过天数
	 * @param localDateTime
	 * @return
	 */
	public static int getPassDayOfQuarter(LocalDateTime localDateTime) {
		int day = 0;
		Month month = localDateTime.getMonth();
		if (month == Month.JANUARY || month == Month.APRIL
				|| month == Month.JULY || month == Month.OCTOBER) {// 季度第一个月
			day = getPassDayOfMonth(localDateTime);
		} else if (month == Month.FEBRUARY || month == Month.MAY
				|| month == Month.AUGUST || month == Month.NOVEMBER) {// 季度第二个月
			day = getDayOfMonth(minusMonth(localDateTime,1L))
					+ getPassDayOfMonth(localDateTime);
		} else if (month == Month.MARCH || month == Month.JUNE
				|| month == Month.SEPTEMBER || month == Month.DECEMBER) {// 季度第三个月
			day = getDayOfMonth(minusMonth(localDateTime,1L)) + getDayOfMonth(minusMonth(localDateTime,2L))
					+ getPassDayOfMonth(localDateTime);
		}
		return day;
	}

	/**
	 * 获取所传LocalDateTime已经过的天数
	 *
	 * @param localDateTime
	 * @return
	 */
	public static int getPassDayOfMonth(LocalDateTime localDateTime) {
		return localDateTime.getDayOfMonth();
	}

	/**
	 * 获取所传LocalDateTime所在月天数
	 * @param localDateTime
	 * @return
	 */
	public static int getDayOfMonth(LocalDateTime localDateTime) {
		return localDateTime.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
	}

	/**
	 * 获取所传LocalDateTime所在月第一天
	 * @param localDateTime
	 * @return
	 */
	public static LocalDateTime getFirstDayOfMonth(LocalDateTime localDateTime) {
		return localDateTime.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
	}

	/**
	 * 获取所传LocalDateTime所在月最后一天
	 * @param localDateTime
	 * @return
	 */
	public static LocalDateTime getLastDayOfMonth(LocalDateTime localDateTime) {
		return localDateTime.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
	}

	public static void main(String[] args) {
		val localDateTime = LocalDateTimeUtils.getNow();
//		System.out.println(localDateTime);
//		val localDateTimeTemp = LocalDateTimeUtils.plusMinutes(localDateTime,5L);
//		System.out.println(localDateTimeTemp.toString());
//		System.out.println(LocalDateTimeUtils.betweenTwoTime(localDateTime,localDateTimeTemp,ChronoUnit.MINUTES).toString());
//		System.out.println(convertStringToLocalDateTime("20180129172506",SIMPLE_DATETIME_FORMAT));
//		System.out.println(2*60*60*1000);
//		System.out.println(getCurrentQuarter());
//		System.out.println(getCurrentYear().toString().substring(3));
//		System.out.println(getDayOfMonth(getNow()));
//		System.out.println(getPassDayOfMonth(getNow()));
//		System.out.println(getPassDayOfQuarter(getNow()));
//		System.out.println(String.format("%02d",getPassDayOfQuarter(convertStringToLocalDateTime("2018-01-02 12:12:12",DEFAULT_DATETIME_FORMAT))));
//		System.out.println(String.format("%03d", LocalDateTimeUtils.getPassDayOfQuarter(LocalDateTimeUtils.getNow())));
		System.out.println(getFirstDayOfMonth(getNow()));
		System.out.println(getLastDayOfMonth(getNow()));

//		startTime = LocalDateTimeUtils.convertLocalDateTimeToDate(LocalDateTimeUtils.getDayStart(LocalDateTimeUtils.convertStringToLocalDateTime(shopOrderDetailsRequest.getStartTime(),LocalDateTimeUtils.DEFAULT_DATE_FORMAT)))
	}
}
