package ru.maximum13.wsdemo.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;

/**
 * Набор утилитных методов для работы с датой и временем.
 *
 * @author MAXIMUM13
 */
public final class DateTimeUtils {

    public static Calendar calendarOf(int year, int month, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, day);
        return calendar;
    }

    public static Calendar calendarOf(int year, int month, int day, int hours, int min) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, day, hours, min);
        return calendar;
    }

    public static Calendar calendarOf(int year, int month, int day, int hours, int min, int sec) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, day, hours, min, sec);
        return calendar;
    }

    public static Calendar calendarOf(int year, int month, int day, int hours, int min, int sec, int ms) {
        Calendar calendar = calendarOf(year, month, day, hours, min, sec);
        calendar.set(Calendar.MILLISECOND, ms);
        return calendar;
    }

    public static Date dateOf(int year, int month, int day) {
        return calendarOf(year, month, day).getTime();
    }

    public static Date dateOf(int year, int month, int day, int hours, int min) {
        return calendarOf(year, month, day, hours, min).getTime();
    }

    public static Date dateOf(int year, int month, int day, int hours, int min, int sec) {
        return calendarOf(year, month, day, hours, min, sec).getTime();
    }

    public static Date dateOf(int year, int month, int day, int hours, int min, int sec, int ms) {
        return calendarOf(year, month, day, hours, min, sec, ms).getTime();
    }

    /**
     * Проверяет, следует ли первая дата за второй или равна ей (great or equals).
     *
     * @param firstDate
     *         первая дата
     * @param secondDate
     *         вторая дата
     */
    public static boolean ge(Date firstDate, Date secondDate) {
        return firstDate.compareTo(secondDate) >= 0;
    }

    /**
     * Проверяет, предшествует ли первая дата второй или равна ей (less or equals).
     *
     * @param firstDate
     *         первая дата
     * @param secondDate
     *         вторая дата
     */
    public static boolean le(Date firstDate, Date secondDate) {
        return firstDate.compareTo(secondDate) <= 0;
    }

    /**
     * Возвращает строку с текущей датой, отформатированной по переданному шаблону.
     *
     * @param dateFormat
     *         шаблон даты
     */
    public static String formatCurrentDate(final String dateFormat) {
        return format(new Date(), dateFormat);
    }

    /**
     * Возвращает строку с датой, отформатированной по переданному шаблону.
     *
     * @param date
     *         дата
     * @param dateFormat
     *         шаблон даты
     */
    public static String format(final Date date, final String dateFormat) {
        return new SimpleDateFormat(dateFormat).format(date);
    }

    /**
     * Обнуляет количество часов, минут, секунд и миллисекунд у переданного календаря.
     */
    public static void resetTime(final Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
    }

    /**
     * Возвращает строку, содержащую текущее время в миллисекундах.
     */
    public static String currentTimeMillisString() {
        return Long.toString(System.currentTimeMillis());
    }

    /**
     * Возвращает новую дату, отличающуюся от переданной на заданное значение.
     *
     * @param date
     *         первоначальная дата
     * @param value
     *         значение единицы времени, на которую нужно изменить дату
     * @param unit
     *         единица времени, в которой задано изменение
     */
    public static Date changeDate(final Date date, final long value, final TimeUnit unit) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTimeInMillis(date.getTime() + unit.toMillis(value));
        return calendar.getTime();
    }

    private DateTimeUtils() {
        ErrorUtils.throwPrivateMethodAccessError(this);
    }
}
