package org.wordpress.android.util;

import android.content.Context;
import android.text.format.DateUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class DateTimeUtils {
    private DateTimeUtils() {
        throw new AssertionError();
    }

    // See http://drdobbs.com/java/184405382
    private static final ThreadLocal<DateFormat> ISO8601_FORMAT = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
        }
    };

    /**
     * Converts a date to a relative time span ("8h", "3d", etc.) - similar to
     * DateUtils.getRelativeTimeSpanString but returns shorter result
     */
    public static String javaDateToTimeSpan(final Date date, Context context) {
        if (date == null) {
            return "";
        }

        long passedTime = date.getTime();
        long currentTime = System.currentTimeMillis();

        // return "now" if less than a minute has elapsed
        long secondsSince = (currentTime - passedTime) / 1000;
        if (secondsSince < 60) {
            return context.getString(R.string.timespan_now);
        }

        // less than an hour (ex: 12m)
        long minutesSince = secondsSince / 60;
        if (minutesSince < 60) {
            return Long.toString(minutesSince) + "m";
        }

        // less than a day (ex: 17h)
        long hoursSince = minutesSince / 60;
        if (hoursSince < 24) {
            return Long.toString(hoursSince) + "h";
        }

        // less than a week (ex: 5d)
        long daysSince = hoursSince / 24;
        if (daysSince < 7) {
            return Long.toString(daysSince) + "d";
        }

        // less than a year old, so return day/month without year (ex: Jan 30)
        if (daysSince < 365) {
            return DateUtils.formatDateTime(context, passedTime, DateUtils.FORMAT_NO_YEAR |
                    DateUtils.FORMAT_ABBREV_ALL);
        }

        // date is older, so include year (ex: Jan 30, 2013)
        return DateUtils.formatDateTime(context, passedTime, DateUtils.FORMAT_ABBREV_ALL);
    }

    /**
     * Given an ISO 8601-formatted date as a String, returns a {@link Date}.
     */
    public static Date dateFromIso8601(final String strDate) {
        try {
            DateFormat formatter = ISO8601_FORMAT.get();
            return formatter.parse(strDate);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * Given an ISO 8601-formatted date as a String, returns a {@link Date} in UTC.
     */
    public static Date dateUTCFromIso8601(String iso8601date) {
        try {
            iso8601date = iso8601date.replace("Z", "+0000").replace("+00:00", "+0000");
            DateFormat formatter = ISO8601_FORMAT.get();
            formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
            return formatter.parse(iso8601date);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * Given a {@link Date}, returns an ISO 8601-formatted String.
     */
    public static String iso8601FromDate(Date date) {
        if (date == null) {
            return "";
        }
        DateFormat formatter = ISO8601_FORMAT.get();
        return formatter.format(date);
    }

    /**
     * Given a {@link Date}, returns an ISO 8601-formatted String in UTC.
     */
    public static String iso8601UTCFromDate(Date date) {
        if (date == null) {
            return "";
        }
        TimeZone tz = TimeZone.getTimeZone("UTC");
        DateFormat formatter = ISO8601_FORMAT.get();
        formatter.setTimeZone(tz);

        String iso8601date = formatter.format(date);

        // Use "+00:00" notation rather than "+0000" to be consistent with the WP.COM API
        return iso8601date.replace("+0000", "+00:00");
    }

    /**
     * Returns the current UTC date
     */
    public static Date nowUTC() {
        Date dateTimeNow = new Date();
        return localDateToUTC(dateTimeNow);
    }

    public static Date localDateToUTC(Date dtLocal) {
        if (dtLocal == null) {
            return null;
        }
        TimeZone tz = TimeZone.getDefault();
        int currentOffsetFromUTC = tz.getRawOffset() + (tz.inDaylightTime(dtLocal) ? tz.getDSTSavings() : 0);
        return new Date(dtLocal.getTime() - currentOffsetFromUTC);
    }

    // Routines to return a diff between two dates - always return a positive number

    public static int daysBetween(Date dt1, Date dt2) {
        long hrDiff = hoursBetween(dt1, dt2);
        if (hrDiff == 0) {
            return 0;
        }
        return (int) (hrDiff / 24);
    }

    public static int hoursBetween(Date dt1, Date dt2) {
        long minDiff = minutesBetween(dt1, dt2);
        if (minDiff == 0) {
            return 0;
        }
        return (int) (minDiff / 60);
    }

    public static int minutesBetween(Date dt1, Date dt2) {
        long msDiff = millisecondsBetween(dt1, dt2);
        if (msDiff == 0) {
            return 0;
        }
        return (int) (msDiff / 60000);
    }

    public static int secondsBetween(Date dt1, Date dt2) {
        long msDiff = millisecondsBetween(dt1, dt2);
        if (msDiff == 0) {
            return 0;
        }
        return (int) (msDiff / 1000);
    }

    public static long millisecondsBetween(Date dt1, Date dt2) {
        if (dt1 == null || dt2 == null) {
            return 0;
        }
        return Math.abs(dt1.getTime() - dt2.getTime());
    }

    public static boolean isSameYear(Date dt1, Date dt2) {
        if (dt1 == null || dt2 == null) {
            return false;
        }
        return dt1.getYear() == dt2.getYear();
    }

    public static boolean isSameMonthAndYear(Date dt1, Date dt2) {
        if (dt1 == null || dt2 == null) {
            return false;
        }
        return dt1.getYear() == dt2.getYear() && dt1.getMonth() == dt2.getMonth();
    }

    // Routines involving Unix timestamps (GMT assumed)

    /**
     * Given an ISO 8601-formatted date as a String, returns the corresponding UNIX timestamp.
     */
    public static long timestampFromIso8601(final String strDate) {
        return (timestampFromIso8601Millis(strDate) / 1000);
    }

    /**
     * Given an ISO 8601-formatted date as a String, returns the corresponding timestamp in milliseconds.
     */
    public static long timestampFromIso8601Millis(final String strDate) {
        Date date = dateFromIso8601(strDate);
        if (date == null) {
            return 0;
        }
        return (date.getTime());
    }

    /**
     * Given a UNIX timestamp, returns the corresponding {@link Date}.
     */
    public static Date dateFromTimestamp(long timestamp) {
        return new java.util.Date(timestamp * 1000);
    }

    /**
     * Given a UNIX timestamp, returns an ISO 8601-formatted date as a String.
     */
    public static String iso8601FromTimestamp(long timestamp) {
        return iso8601FromDate(dateFromTimestamp(timestamp));
    }

    /**
     * Given a UNIX timestamp, returns an ISO 8601-formatted date in UTC as a String.
     */
    public static String iso8601UTCFromTimestamp(long timestamp) {
        return iso8601UTCFromDate(dateFromTimestamp(timestamp));
    }

    /**
     * Given a UNIX timestamp, returns a relative time span ("8h", "3d", etc.).
     */
    public static String timeSpanFromTimestamp(long timestamp, Context context) {
        Date dateGMT = dateFromTimestamp(timestamp);
        return javaDateToTimeSpan(dateGMT, context);
    }
}
