/*
 * Copyright 2017 Phillip Hsu
 *
 * This file is part of ClockPlus.
 *
 * ClockPlus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ClockPlus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ClockPlus.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.philliphsu.clock2.util;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;

import com.philliphsu.clock2.R;

import java.util.concurrent.TimeUnit;

/**
 * Created by Phillip Hsu on 6/6/2016.
 */
public class DurationUtils {
    public static final int DAYS = 0;
    public static final int HOURS = 1;
    public static final int MINUTES = 2;
    public static final int SECONDS = 3;
    public static final int MILLIS = 4;

    /** Return a string representing the duration, formatted in hours and minutes.
     * TODO: Need to adapt this to represent all time fields eventually
     * TODO: Since this is primarirly used for alarm set toasts, you should make different methods for
     * different use cases. E.g. Timer's duration should have its own method.
     * TODO: Then, rename this method to something about alarm toasts. */
    public static String toString(Context context, long millis, boolean abbreviate) {
        long[] fields = breakdown(millis);
        long numDays = fields[DAYS];
        long numHours = fields[HOURS];
        long numMins = fields[MINUTES];
        long numSecs = fields[SECONDS]; // only considered for rounding of minutes
        if (numSecs >= 31) {
            numMins++;
            numSecs = 0; // Not totally necessary since it won't be considered any more
            if (numMins == 60) {
                numHours++;
                numMins = 0;
                if (numHours == 24) {
                    numDays++;
                    numHours = 0;
                }
            }
        }

        int res;
        if (abbreviate) {
            res = getAbbreviatedStringRes(numDays, numHours, numMins);
        } else {
            res = getStringRes(numDays, numHours, numMins);
        }
        
        return context.getString(res, numDays, numHours, numMins);
    }

    /**
     * Equivalent to
     * {@link #breakdown(long, TimeUnit, boolean)
     * breakdown(millis, TimeUnit.MILLISECONDS, true)},
     * which rounds milliseconds. Callers who use this are probably not
     * concerned about displaying the milliseconds value.
     */
    public static long[] breakdown(long millis) {
        return breakdown(millis, TimeUnit.MILLISECONDS, true);
    }

    /**
     * Equivalent to
     * {@link #breakdown(long, TimeUnit, boolean) breakdown(t, unit, false)},
     * i.e. does not round milliseconds.
     */
    public static long[] breakdown(long t, @NonNull TimeUnit unit) {
        return breakdown(t, unit, false);
    }

    /**
     * Returns a breakdown of a given time into its values
     * in hours, minutes, seconds and milliseconds.
     * @param t the time to break down
     * @param unit the {@link TimeUnit} the given time is expressed in
     * @param roundMillis whether rounding of milliseconds is desired
     * @return a {@code long[]} of the values in hours, minutes, seconds
     *         and milliseconds in that order
     */
    public static long[] breakdown(long t, @NonNull TimeUnit unit, boolean roundMillis) {
        long days = unit.toDays(t);
        long hours = unit.toHours(t) % 24;
        long minutes = unit.toMinutes(t) % 60;
        long seconds = unit.toSeconds(t) % 60;
        long msecs = unit.toMillis(t) % 1000;
        if (roundMillis) {
            if (msecs >= 500) {
                seconds++;
                msecs = 0;
                if (seconds == 60) {
                    minutes++;
                    seconds = 0;
                    if (minutes == 60) {
                        hours++;
                        minutes = 0;
                        if (hours == 24) {
                            days++;
                            hours = 0;
                        }
                    }
                }
            }
        }
        return new long[] { days, hours, minutes, seconds, msecs };
    }

    @StringRes
    private static int getStringRes(long numDays, long numHours, long numMins) {
        int res;
        if (numDays == 0) {
            if (numHours == 0) {
                if (numMins == 0) {
                    res = R.string.less_than_one_minute;
                } else if (numMins == 1) {
                    res = R.string.minute;
                } else {
                    res = R.string.minutes;
                }
            } else if (numHours == 1) {
                if (numMins == 0) {
                    res = R.string.hour;
                } else if (numMins == 1) {
                    res = R.string.hour_and_minute;
                } else {
                    res = R.string.hour_and_minutes;
                }
            } else {
                if (numMins == 0) {
                    res = R.string.hours;
                } else if (numMins == 1) {
                    res = R.string.hours_and_minute;
                } else {
                    res = R.string.hours_and_minutes;
                }
            }
        } else if (numDays == 1) {
            if (numHours == 0) {
                if (numMins == 0) {
                    res = R.string.day;
                } else if (numMins == 1) {
                    res = R.string.day_and_minute;
                } else {
                    res = R.string.day_and_minutes;
                }
            } else if (numHours == 1) {
                if (numMins == 0) {
                    res = R.string.day_and_hour;
                } else if (numMins == 1) {
                    res = R.string.day_hour_and_minute;
                } else {
                    res = R.string.day_hour_and_minutes;
                }
            } else {
                if (numMins == 0) {
                    res = R.string.day_and_hours;
                } else if (numMins == 1) {
                    res = R.string.day_hours_and_minute;
                } else {
                    res = R.string.day_hours_and_minutes;
                }
            }
        } else {
            if (numHours == 0) {
                if (numMins == 0) {
                    res = R.string.days;
                } else if (numMins == 1) {
                    res = R.string.days_and_minute;
                } else {
                    res = R.string.days_and_minutes;
                }
            } else if (numHours == 1) {
                if (numMins == 0) {
                    res = R.string.days_and_hour;
                } else if (numMins == 1) {
                    res = R.string.days_hour_and_minute;
                } else {
                    res = R.string.days_hour_and_minutes;
                }
            } else {
                if (numMins == 0) {
                    res = R.string.days_and_hours;
                } else if (numMins == 1) {
                    res = R.string.days_hours_and_minute;
                } else {
                    res = R.string.days_hours_and_minutes;
                }
            }
        }
        return res;
    }

    @StringRes
    private static int getAbbreviatedStringRes(long numDays, long numHours, long numMins) {
        int res;
        if (numDays == 0) {
            if (numHours == 0) {
                if (numMins == 0) {
                    res = R.string.abbrev_less_than_one_minute;
                } else {
                    res = R.string.abbrev_minutes;
                }
            } else {
                if (numMins == 0) {
                    res = R.string.abbrev_hours;
                } else {
                    res = R.string.abbrev_hours_and_minutes;
                }
            }
        } else {
            if (numHours == 0) {
                if (numMins == 0) {
                    res = R.string.abbrev_days;
                } else {
                    res = R.string.abbrev_days_and_minutes;
                }
            } else {
                if (numMins == 0) {
                    res = R.string.abbrev_days_and_hours;
                } else {
                    res = R.string.abbrev_days_hours_and_minutes;
                }
            }
        }
        return res;
    }


}