/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.calendar

import android.app.Activity
import android.content.ComponentName
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.content.res.Resources
import android.database.Cursor
import android.database.MatrixCursor
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.provider.CalendarContract.Calendars
import android.provider.CalendarContract.EXTRA_EVENT_BEGIN_TIME
import android.text.TextUtils
import android.text.format.DateFormat
import android.text.format.DateUtils
import android.text.format.Time
import android.util.Log
import com.android.calendar.CalendarController.ViewType
import com.android.calendar.CalendarUtils.TimeZoneUtils
import java.util.ArrayList
import java.util.Arrays
import java.util.Calendar
import java.util.Formatter
import java.util.HashMap
import java.util.LinkedHashSet
import java.util.LinkedList
import java.util.List
import java.util.Locale
import java.util.TimeZone
import java.util.regex.Pattern

object Utils {
    private const val DEBUG = false
    private const val TAG = "CalUtils"

    // Set to 0 until we have UI to perform undo
    const val UNDO_DELAY: Long = 0

    // For recurring events which instances of the series are being modified
    const val MODIFY_UNINITIALIZED = 0
    const val MODIFY_SELECTED = 1
    const val MODIFY_ALL_FOLLOWING = 2
    const val MODIFY_ALL = 3

    // When the edit event view finishes it passes back the appropriate exit
    // code.
    const val DONE_REVERT = 1 shl 0
    const val DONE_SAVE = 1 shl 1
    const val DONE_DELETE = 1 shl 2

    // And should re run with DONE_EXIT if it should also leave the view, just
    // exiting is identical to reverting
    const val DONE_EXIT = 1 shl 0
    const val OPEN_EMAIL_MARKER = " <"
    const val CLOSE_EMAIL_MARKER = ">"
    const val INTENT_KEY_DETAIL_VIEW = "DETAIL_VIEW"
    const val INTENT_KEY_VIEW_TYPE = "VIEW"
    const val INTENT_VALUE_VIEW_TYPE_DAY = "DAY"
    const val INTENT_KEY_HOME = "KEY_HOME"
    val MONDAY_BEFORE_JULIAN_EPOCH: Int = Time.EPOCH_JULIAN_DAY - 3
    const val DECLINED_EVENT_ALPHA = 0x66
    const val DECLINED_EVENT_TEXT_ALPHA = 0xC0
    private const val SATURATION_ADJUST = 1.3f
    private const val INTENSITY_ADJUST = 0.8f

    // Defines used by the DNA generation code
    const val DAY_IN_MINUTES = 60 * 24
    const val WEEK_IN_MINUTES = DAY_IN_MINUTES * 7

    // The work day is being counted as 6am to 8pm
    var WORK_DAY_MINUTES = 14 * 60
    var WORK_DAY_START_MINUTES = 6 * 60
    var WORK_DAY_END_MINUTES = 20 * 60
    var WORK_DAY_END_LENGTH = 24 * 60 - WORK_DAY_END_MINUTES
    var CONFLICT_COLOR = -0x1000000
    var mMinutesLoaded = false
    const val YEAR_MIN = 1970
    const val YEAR_MAX = 2036

    // The name of the shared preferences file. This name must be maintained for
    // historical
    // reasons, as it's what PreferenceManager assigned the first time the file
    // was created.
    const val SHARED_PREFS_NAME = "com.android.calendar_preferences"
    const val KEY_QUICK_RESPONSES = "preferences_quick_responses"
    const val KEY_ALERTS_VIBRATE_WHEN = "preferences_alerts_vibrateWhen"
    const val APPWIDGET_DATA_TYPE = "vnd.android.data/update"
    const val MACHINE_GENERATED_ADDRESS = "calendar.google.com"
    private val mTZUtils: TimeZoneUtils? = TimeZoneUtils(SHARED_PREFS_NAME)
    @JvmField var allowWeekForDetailView = false
    internal var tardis: Long = 0
        private set
    private var sVersion: String? = null
    private val mWildcardPattern: Pattern = Pattern.compile("^.*$")

    /**
     * A coordinate must be of the following form for Google Maps to correctly use it:
     * Latitude, Longitude
     *
     * This may be in decimal form:
     * Latitude: {-90 to 90}
     * Longitude: {-180 to 180}
     *
     * Or, in degrees, minutes, and seconds:
     * Latitude: {-90 to 90}° {0 to 59}' {0 to 59}"
     * Latitude: {-180 to 180}° {0 to 59}' {0 to 59}"
     * + or - degrees may also be represented with N or n, S or s for latitude, and with
     * E or e, W or w for longitude, where the direction may either precede or follow the value.
     *
     * Some examples of coordinates that will be accepted by the regex:
     * 37.422081°, -122.084576°
     * 37.422081,-122.084576
     * +37°25'19.49", -122°5'4.47"
     * 37°25'19.49"N, 122°5'4.47"W
     * N 37° 25' 19.49",  W 122° 5' 4.47"
     */
    private const val COORD_DEGREES_LATITUDE = ("([-+NnSs]" + "(\\s)*)?" +
        "[1-9]?[0-9](\u00B0)" + "(\\s)*" +
        "([1-5]?[0-9]\')?" + "(\\s)*" +
        "([1-5]?[0-9]" + "(\\.[0-9]+)?\")?" +
        "((\\s)*" + "[NnSs])?")
    private const val COORD_DEGREES_LONGITUDE = ("([-+EeWw]" + "(\\s)*)?" +
        "(1)?[0-9]?[0-9](\u00B0)" + "(\\s)*" +
        "([1-5]?[0-9]\')?" + "(\\s)*" +
        "([1-5]?[0-9]" + "(\\.[0-9]+)?\")?" +
        "((\\s)*" + "[EeWw])?")
    private const val COORD_DEGREES_PATTERN = (COORD_DEGREES_LATITUDE + "(\\s)*" + "," + "(\\s)*" +
        COORD_DEGREES_LONGITUDE)
    private const val COORD_DECIMAL_LATITUDE = ("[+-]?" +
        "[1-9]?[0-9]" + "(\\.[0-9]+)" +
        "(\u00B0)?")
    private const val COORD_DECIMAL_LONGITUDE = ("[+-]?" +
        "(1)?[0-9]?[0-9]" + "(\\.[0-9]+)" +
        "(\u00B0)?")
    private const val COORD_DECIMAL_PATTERN = (COORD_DECIMAL_LATITUDE + "(\\s)*" + "," + "(\\s)*" +
        COORD_DECIMAL_LONGITUDE)
    private val COORD_PATTERN: Pattern =
        Pattern.compile(COORD_DEGREES_PATTERN + "|" + COORD_DECIMAL_PATTERN)
    private const val NANP_ALLOWED_SYMBOLS = "()+-*#."
    private const val NANP_MIN_DIGITS = 7
    private const val NANP_MAX_DIGITS = 11

    /**
     * Returns whether the SDK is the KeyLimePie release or later.
     */
    @JvmStatic fun isKeyLimePieOrLater(): Boolean {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
    }

    /**
     * Returns whether the SDK is the Jellybean release or later.
     */
    @JvmStatic fun isJellybeanOrLater(): Boolean {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
    }

    @JvmStatic fun getViewTypeFromIntentAndSharedPref(activity: Activity): Int {
        val intent: Intent? = activity.getIntent()
        val extras: Bundle? = intent?.getExtras()
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(activity)
        if (TextUtils.equals(intent?.getAction(), Intent.ACTION_EDIT)) {
            return ViewType.EDIT
        }
        if (extras != null) {
            if (extras?.getBoolean(INTENT_KEY_DETAIL_VIEW, false)) {
                // This is the "detail" view which is either agenda or day view
                return prefs?.getInt(
                    GeneralPreferences.KEY_DETAILED_VIEW,
                    GeneralPreferences.DEFAULT_DETAILED_VIEW
                ) as Int
            } else if (INTENT_VALUE_VIEW_TYPE_DAY.equals(extras?.getString(INTENT_KEY_VIEW_TYPE))) {
                // Not sure who uses this. This logic came from LaunchActivity
                return ViewType.DAY
            }
        }

        // Default to the last view
        return prefs?.getInt(
            GeneralPreferences.KEY_START_VIEW, GeneralPreferences.DEFAULT_START_VIEW
        ) as Int
    }

    /**
     * Gets the intent action for telling the widget to update.
     */
    @JvmStatic fun getWidgetUpdateAction(context: Context): String {
        return context.getPackageName().toString() + ".APPWIDGET_UPDATE"
    }

    /**
     * Gets the intent action for telling the widget to update.
     */
    @JvmStatic fun getWidgetScheduledUpdateAction(context: Context): String {
        return context.getPackageName().toString() + ".APPWIDGET_SCHEDULED_UPDATE"
    }

    /**
     * Writes a new home time zone to the db. Updates the home time zone in the
     * db asynchronously and updates the local cache. Sending a time zone of
     * **tbd** will cause it to be set to the device's time zone. null or empty
     * tz will be ignored.
     *
     * @param context The calling activity
     * @param timeZone The time zone to set Calendar to, or **tbd**
     */
    @JvmStatic fun setTimeZone(context: Context?, timeZone: String?) {
        mTZUtils?.setTimeZone(context as Context, timeZone as String)
    }

    /**
     * Gets the time zone that Calendar should be displayed in This is a helper
     * method to get the appropriate time zone for Calendar. If this is the
     * first time this method has been called it will initiate an asynchronous
     * query to verify that the data in preferences is correct. The callback
     * supplied will only be called if this query returns a value other than
     * what is stored in preferences and should cause the calling activity to
     * refresh anything that depends on calling this method.
     *
     * @param context The calling activity
     * @param callback The runnable that should execute if a query returns new
     * values
     * @return The string value representing the time zone Calendar should
     * display
     */
    @JvmStatic fun getTimeZone(context: Context?, callback: Runnable?): String? {
        return mTZUtils?.getTimeZone(context as Context, callback)
    }

    /**
     * Formats a date or a time range according to the local conventions.
     *
     * @param context the context is required only if the time is shown
     * @param startMillis the start time in UTC milliseconds
     * @param endMillis the end time in UTC milliseconds
     * @param flags a bit mask of options See [formatDateRange][DateUtils.formatDateRange]
     * @return a string containing the formatted date/time range.
     */
    @JvmStatic fun formatDateRange(
        context: Context?,
        startMillis: Long,
        endMillis: Long,
        flags: Int
    ): String? {
        return mTZUtils?.formatDateRange(context as Context, startMillis, endMillis, flags)
    }

    @JvmStatic fun getDefaultVibrate(context: Context, prefs: SharedPreferences?): Boolean {
        val vibrate: Boolean
        if (prefs?.contains(KEY_ALERTS_VIBRATE_WHEN) == true) {
            // Migrate setting to new 4.2 behavior
            //
            // silent and never -> off
            // always -> on
            val vibrateWhen: String? = prefs?.getString(KEY_ALERTS_VIBRATE_WHEN, null)
            vibrate = vibrateWhen != null && vibrateWhen.equals(
                context
                    .getString(R.string.prefDefault_alerts_vibrate_true)
            )
            prefs?.edit().remove(KEY_ALERTS_VIBRATE_WHEN).commit()
            Log.d(
                TAG, "Migrating KEY_ALERTS_VIBRATE_WHEN(" +
                    vibrateWhen + ") to KEY_ALERTS_VIBRATE = " + vibrate
            )
        } else {
            vibrate = prefs?.getBoolean(
                GeneralPreferences.KEY_ALERTS_VIBRATE,
                false
            ) as Boolean
        }
        return vibrate
    }

    @JvmStatic fun getSharedPreference(
        context: Context?,
        key: String?,
        defaultValue: Array<String>?
    ): Array<String>? {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        val ss = prefs?.getStringSet(key, null)
        if (ss != null) {
            val strings = arrayOfNulls<String>(ss?.size)
            return ss?.toTypedArray()
        }
        return defaultValue
    }

    @JvmStatic fun getSharedPreference(
        context: Context?,
        key: String?,
        defaultValue: String?
    ): String? {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        return prefs?.getString(key, defaultValue)
    }

    @JvmStatic fun getSharedPreference(context: Context?, key: String?, defaultValue: Int): Int {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        return prefs?.getInt(key, defaultValue) as Int
    }

    @JvmStatic fun getSharedPreference(
        context: Context?,
        key: String?,
        defaultValue: Boolean
    ): Boolean {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        return prefs?.getBoolean(key, defaultValue) as Boolean
    }

    /**
     * Asynchronously sets the preference with the given key to the given value
     *
     * @param context the context to use to get preferences from
     * @param key the key of the preference to set
     * @param value the value to set
     */
    @JvmStatic fun setSharedPreference(context: Context?, key: String?, value: String?) {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        prefs?.edit()?.putString(key, value)?.apply()
    }

    @JvmStatic fun setSharedPreference(context: Context?, key: String?, values: Array<String?>) {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        val set: LinkedHashSet<String?> = LinkedHashSet<String?>()
        for (value in values) {
            set.add(value)
        }
        prefs?.edit()?.putStringSet(key, set)?.apply()
    }

    internal fun tardis() {
        tardis = System.currentTimeMillis()
    }

    @JvmStatic fun setSharedPreference(context: Context?, key: String?, value: Boolean) {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        val editor: SharedPreferences.Editor? = prefs?.edit()
        editor?.putBoolean(key, value)
        editor?.apply()
    }

    @JvmStatic fun setSharedPreference(context: Context?, key: String?, value: Int) {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        val editor: SharedPreferences.Editor? = prefs?.edit()
        editor?.putInt(key, value)
        editor?.apply()
    }

    @JvmStatic fun removeSharedPreference(context: Context?, key: String?) {
        val prefs: SharedPreferences? = context?.getSharedPreferences(
            GeneralPreferences.SHARED_PREFS_NAME, Context.MODE_PRIVATE
        )
        prefs?.edit()?.remove(key)?.apply()
    }

    /**
     * Save default agenda/day/week/month view for next time
     *
     * @param context
     * @param viewId [CalendarController.ViewType]
     */
    @JvmStatic fun setDefaultView(context: Context?, viewId: Int) {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        val editor: SharedPreferences.Editor? = prefs?.edit()
        var validDetailView = false
        validDetailView =
            if (allowWeekForDetailView && viewId == CalendarController.ViewType.WEEK) {
                true
            } else {
                (viewId == CalendarController.ViewType.AGENDA ||
                    viewId == CalendarController.ViewType.DAY)
            }
        if (validDetailView) {
            // Record the detail start view
            editor?.putInt(GeneralPreferences.KEY_DETAILED_VIEW, viewId)
        }

        // Record the (new) start view
        editor?.putInt(GeneralPreferences.KEY_START_VIEW, viewId)
        editor?.apply()
    }

    @JvmStatic fun matrixCursorFromCursor(cursor: Cursor?): MatrixCursor? {
        if (cursor == null) {
            return null
        }
        var columnNames: Array<String?> = cursor.getColumnNames()
        if (columnNames == null) {
            columnNames = arrayOf()
        }
        val newCursor = MatrixCursor(columnNames)
        val numColumns: Int = cursor.getColumnCount()
        val data = arrayOfNulls<String>(numColumns)
        cursor.moveToPosition(-1)
        while (cursor.moveToNext()) {
            for (i in 0 until numColumns) {
                data[i] = cursor.getString(i)
            }
            newCursor.addRow(data)
        }
        return newCursor
    }

    /**
     * Compares two cursors to see if they contain the same data.
     *
     * @return Returns true of the cursors contain the same data and are not
     * null, false otherwise
     */
    @JvmStatic fun compareCursors(c1: Cursor?, c2: Cursor?): Boolean {
        if (c1 == null || c2 == null) {
            return false
        }
        val numColumns: Int = c1.getColumnCount()
        if (numColumns != c2.getColumnCount()) {
            return false
        }
        if (c1.getCount() !== c2.getCount()) {
            return false
        }
        c1.moveToPosition(-1)
        c2.moveToPosition(-1)
        while (c1.moveToNext() && c2.moveToNext()) {
            for (i in 0 until numColumns) {
                if (!TextUtils.equals(c1.getString(i), c2.getString(i))) {
                    return false
                }
            }
        }
        return true
    }

    /**
     * If the given intent specifies a time (in milliseconds since the epoch),
     * then that time is returned. Otherwise, the current time is returned.
     */
    @JvmStatic fun timeFromIntentInMillis(intent: Intent?): Long? {
        // If the time was specified, then use that. Otherwise, use the current
        // time.
        val data: Uri? = intent?.getData()
        var millis: Long? = intent?.getLongExtra(EXTRA_EVENT_BEGIN_TIME, -1)?.toLong()
        if (millis == -1L && data != null && data?.isHierarchical()) {
            val path: List<String> = data?.getPathSegments() as List<String>
            if (path.size == 2 && path[0].equals("time")) {
                try {
                    millis = (data?.getLastPathSegment()?.toLong())
                } catch (e: NumberFormatException) {
                    Log.i(
                        "Calendar", "timeFromIntentInMillis: Data existed but no valid time " +
                            "found. Using current time."
                    )
                }
            }
        }
        if ((millis ?: 0L) <= 0) {
            millis = System.currentTimeMillis()
        }
        return millis
    }

    /**
     * Formats the given Time object so that it gives the month and year (for
     * example, "September 2007").
     *
     * @param time the time to format
     * @return the string containing the weekday and the date
     */
    @JvmStatic fun formatMonthYear(context: Context?, time: Time): String? {
        val flags: Int = (DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_MONTH_DAY
            or DateUtils.FORMAT_SHOW_YEAR)
        val millis: Long = time.toMillis(true)
        return formatDateRange(context, millis, millis, flags)
    }

    /**
     * Returns a list joined together by the provided delimiter, for example,
     * ["a", "b", "c"] could be joined into "a,b,c"
     *
     * @param things the things to join together
     * @param delim the delimiter to use
     * @return a string contained the things joined together
     */
    @JvmStatic fun join(things: List<*>, delim: String?): String {
        val builder = StringBuilder()
        var first = true
        for (thing in things) {
            if (first) {
                first = false
            } else {
                builder.append(delim)
            }
            builder.append(thing.toString())
        }
        return builder.toString()
    }

    /**
     * Returns the week since [Time.EPOCH_JULIAN_DAY] (Jan 1, 1970)
     * adjusted for first day of week.
     *
     * This takes a julian day and the week start day and calculates which
     * week since [Time.EPOCH_JULIAN_DAY] that day occurs in, starting
     * at 0. *Do not* use this to compute the ISO week number for the year.
     *
     * @param julianDay The julian day to calculate the week number for
     * @param firstDayOfWeek Which week day is the first day of the week,
     * see [Time.SUNDAY]
     * @return Weeks since the epoch
     */
    @JvmStatic fun getWeeksSinceEpochFromJulianDay(julianDay: Int, firstDayOfWeek: Int): Int {
        var diff: Int = Time.THURSDAY - firstDayOfWeek
        if (diff < 0) {
            diff += 7
        }
        val refDay: Int = Time.EPOCH_JULIAN_DAY - diff
        return (julianDay - refDay) / 7
    }

    /**
     * Takes a number of weeks since the epoch and calculates the Julian day of
     * the Monday for that week.
     *
     * This assumes that the week containing the [Time.EPOCH_JULIAN_DAY]
     * is considered week 0. It returns the Julian day for the Monday
     * `week` weeks after the Monday of the week containing the epoch.
     *
     * @param week Number of weeks since the epoch
     * @return The julian day for the Monday of the given week since the epoch
     */
    @JvmStatic fun getJulianMondayFromWeeksSinceEpoch(week: Int): Int {
        return MONDAY_BEFORE_JULIAN_EPOCH + week * 7
    }

    /**
     * Get first day of week as android.text.format.Time constant.
     *
     * @return the first day of week in android.text.format.Time
     */
    @JvmStatic fun getFirstDayOfWeek(context: Context?): Int {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        val pref: String? = prefs?.getString(
            GeneralPreferences.KEY_WEEK_START_DAY, GeneralPreferences.WEEK_START_DEFAULT
        )
        val startDay: Int
        startDay = if (GeneralPreferences.WEEK_START_DEFAULT.equals(pref)) {
            Calendar.getInstance().getFirstDayOfWeek()
        } else {
            Integer.parseInt(pref)
        }
        return if (startDay == Calendar.SATURDAY) {
            Time.SATURDAY
        } else if (startDay == Calendar.MONDAY) {
            Time.MONDAY
        } else {
            Time.SUNDAY
        }
    }

    /**
     * Get first day of week as java.util.Calendar constant.
     *
     * @return the first day of week as a java.util.Calendar constant
     */
    @JvmStatic fun getFirstDayOfWeekAsCalendar(context: Context?): Int {
        return convertDayOfWeekFromTimeToCalendar(getFirstDayOfWeek(context))
    }

    /**
     * Converts the day of the week from android.text.format.Time to java.util.Calendar
     */
    @JvmStatic fun convertDayOfWeekFromTimeToCalendar(timeDayOfWeek: Int): Int {
        return when (timeDayOfWeek) {
            Time.MONDAY -> Calendar.MONDAY
            Time.TUESDAY -> Calendar.TUESDAY
            Time.WEDNESDAY -> Calendar.WEDNESDAY
            Time.THURSDAY -> Calendar.THURSDAY
            Time.FRIDAY -> Calendar.FRIDAY
            Time.SATURDAY -> Calendar.SATURDAY
            Time.SUNDAY -> Calendar.SUNDAY
            else -> throw IllegalArgumentException(
                "Argument must be between Time.SUNDAY and " +
                    "Time.SATURDAY"
            )
        }
    }

    /**
     * @return true when week number should be shown.
     */
    @JvmStatic fun getShowWeekNumber(context: Context?): Boolean {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        return prefs?.getBoolean(
            GeneralPreferences.KEY_SHOW_WEEK_NUM, GeneralPreferences.DEFAULT_SHOW_WEEK_NUM
        ) as Boolean
    }

    /**
     * @return true when declined events should be hidden.
     */
    @JvmStatic fun getHideDeclinedEvents(context: Context?): Boolean {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        return prefs?.getBoolean(GeneralPreferences.KEY_HIDE_DECLINED, false) as Boolean
    }

    @JvmStatic fun getDaysPerWeek(context: Context?): Int {
        val prefs: SharedPreferences? = GeneralPreferences.getSharedPreferences(context)
        return prefs?.getInt(GeneralPreferences.KEY_DAYS_PER_WEEK, 7) as Int
    }

    /**
     * Determine whether the column position is Saturday or not.
     *
     * @param column the column position
     * @param firstDayOfWeek the first day of week in android.text.format.Time
     * @return true if the column is Saturday position
     */
    @JvmStatic fun isSaturday(column: Int, firstDayOfWeek: Int): Boolean {
        return (firstDayOfWeek == Time.SUNDAY && column == 6 ||
            firstDayOfWeek == Time.MONDAY && column == 5 ||
            firstDayOfWeek == Time.SATURDAY && column == 0)
    }

    /**
     * Determine whether the column position is Sunday or not.
     *
     * @param column the column position
     * @param firstDayOfWeek the first day of week in android.text.format.Time
     * @return true if the column is Sunday position
     */
    @JvmStatic fun isSunday(column: Int, firstDayOfWeek: Int): Boolean {
        return (firstDayOfWeek == Time.SUNDAY && column == 0 ||
            firstDayOfWeek == Time.MONDAY && column == 6 ||
            firstDayOfWeek == Time.SATURDAY && column == 1)
    }

    /**
     * Convert given UTC time into current local time. This assumes it is for an
     * allday event and will adjust the time to be on a midnight boundary.
     *
     * @param recycle Time object to recycle, otherwise null.
     * @param utcTime Time to convert, in UTC.
     * @param tz The time zone to convert this time to.
     */
    @JvmStatic fun convertAlldayUtcToLocal(recycle: Time?, utcTime: Long, tz: String): Long {
        var recycle: Time? = recycle
        if (recycle == null) {
            recycle = Time()
        }
        recycle.timezone = Time.TIMEZONE_UTC
        recycle.set(utcTime)
        recycle.timezone = tz
        return recycle.normalize(true)
    }

    @JvmStatic fun convertAlldayLocalToUTC(recycle: Time?, localTime: Long, tz: String): Long {
        var recycle: Time? = recycle
        if (recycle == null) {
            recycle = Time()
        }
        recycle.timezone = tz
        recycle.set(localTime)
        recycle.timezone = Time.TIMEZONE_UTC
        return recycle.normalize(true)
    }

    /**
     * Finds and returns the next midnight after "theTime" in milliseconds UTC
     *
     * @param recycle - Time object to recycle, otherwise null.
     * @param theTime - Time used for calculations (in UTC)
     * @param tz The time zone to convert this time to.
     */
    @JvmStatic fun getNextMidnight(recycle: Time?, theTime: Long, tz: String): Long {
        var recycle: Time? = recycle
        if (recycle == null) {
            recycle = Time()
        }
        recycle.timezone = tz
        recycle.set(theTime)
        recycle.monthDay++
        recycle.hour = 0
        recycle.minute = 0
        recycle.second = 0
        return recycle.normalize(true)
    }

    @JvmStatic fun setAllowWeekForDetailView(allowWeekView: Boolean) {
        this.allowWeekForDetailView = allowWeekView
    }

    @JvmStatic fun getAllowWeekForDetailView(): Boolean {
        return this.allowWeekForDetailView
    }

    @JvmStatic fun getConfigBool(c: Context, key: Int): Boolean {
        return c.getResources().getBoolean(key)
    }

    /**
     * For devices with Jellybean or later, darkens the given color to ensure that white text is
     * clearly visible on top of it.  For devices prior to Jellybean, does nothing, as the
     * sync adapter handles the color change.
     *
     * @param color
     */
    @JvmStatic fun getDisplayColorFromColor(color: Int): Int {
        if (!isJellybeanOrLater()) {
            return color
        }
        val hsv = FloatArray(3)
        Color.colorToHSV(color, hsv)
        hsv[1] = Math.min(hsv[1] * SATURATION_ADJUST, 1.0f)
        hsv[2] = hsv[2] * INTENSITY_ADJUST
        return Color.HSVToColor(hsv)
    }

    // This takes a color and computes what it would look like blended with
    // white. The result is the color that should be used for declined events.
    @JvmStatic fun getDeclinedColorFromColor(color: Int): Int {
        val bg = -0x1
        val a = DECLINED_EVENT_ALPHA
        val r = (color and 0x00ff0000) * a + (bg and 0x00ff0000) * (0xff - a) and -0x1000000
        val g = (color and 0x0000ff00) * a + (bg and 0x0000ff00) * (0xff - a) and 0x00ff0000
        val b = (color and 0x000000ff) * a + (bg and 0x000000ff) * (0xff - a) and 0x0000ff00
        return -0x1000000 or (r or g or b shr 8)
    }

    @JvmStatic fun trySyncAndDisableUpgradeReceiver(context: Context?) {
        val pm: PackageManager? = context?.getPackageManager()
        val upgradeComponent = ComponentName(context as Context, UpgradeReceiver::class.java)
        if (pm?.getComponentEnabledSetting(upgradeComponent) ===
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED
        ) {
            // The upgrade receiver has been disabled, which means this code has been run before,
            // so no need to sync.
            return
        }
        val extras = Bundle()
        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
        ContentResolver.requestSync(
            null /* no account */,
            Calendars.CONTENT_URI.getAuthority(),
            extras
        )

        // Now unregister the receiver so that we won't continue to sync every time.
        pm?.setComponentEnabledSetting(
            upgradeComponent,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP
        )
    }

    /**
     * Converts a list of events to a list of segments to draw. Assumes list is
     * ordered by start time of the events. The function processes events for a
     * range of days from firstJulianDay to firstJulianDay + dayXs.length - 1.
     * The algorithm goes over all the events and creates a set of segments
     * ordered by start time. This list of segments is then converted into a
     * HashMap of strands which contain the draw points and are organized by
     * color. The strands can then be drawn by setting the paint color to each
     * strand's color and calling drawLines on its set of points. The points are
     * set up using the following parameters.
     *
     *  * Events between midnight and WORK_DAY_START_MINUTES are compressed
     * into the first 1/8th of the space between top and bottom.
     *  * Events between WORK_DAY_END_MINUTES and the following midnight are
     * compressed into the last 1/8th of the space between top and bottom
     *  * Events between WORK_DAY_START_MINUTES and WORK_DAY_END_MINUTES use
     * the remaining 3/4ths of the space
     *  * All segments drawn will maintain at least minPixels height, except
     * for conflicts in the first or last 1/8th, which may be smaller
     *
     *
     * @param firstJulianDay The julian day of the first day of events
     * @param events A list of events sorted by start time
     * @param top The lowest y value the dna should be drawn at
     * @param bottom The highest y value the dna should be drawn at
     * @param dayXs An array of x values to draw the dna at, one for each day
     * @param conflictColor the color to use for conflicts
     * @return
     */
    @JvmStatic fun createDNAStrands(
        firstJulianDay: Int,
        events: ArrayList<Event?>?,
        top: Int,
        bottom: Int,
        minPixels: Int,
        dayXs: IntArray?,
        context: Context?
    ): HashMap<Int, DNAStrand>? {
        if (!mMinutesLoaded) {
            if (context == null) {
                Log.wtf(TAG, "No context and haven't loaded parameters yet! Can't create DNA.")
            }
            val res: Resources? = context?.getResources()
            CONFLICT_COLOR = res?.getColor(R.color.month_dna_conflict_time_color) as Int
            WORK_DAY_START_MINUTES = res?.getInteger(R.integer.work_start_minutes) as Int
            WORK_DAY_END_MINUTES = res?.getInteger(R.integer.work_end_minutes) as Int
            WORK_DAY_END_LENGTH = DAY_IN_MINUTES - WORK_DAY_END_MINUTES
            WORK_DAY_MINUTES = WORK_DAY_END_MINUTES - WORK_DAY_START_MINUTES
            mMinutesLoaded = true
        }
        if (events == null || events.isEmpty() || dayXs == null || dayXs.size < 1 ||
            bottom - top < 8 || minPixels < 0) {
            Log.e(
                TAG,
                "Bad values for createDNAStrands! events:" + events + " dayXs:" +
                    Arrays.toString(dayXs) + " bot-top:" + (bottom - top) + " minPixels:" +
                    minPixels
            )
            return null
        }
        val segments: LinkedList<DNASegment> = LinkedList<DNASegment>()
        val strands: HashMap<Int, DNAStrand> = HashMap<Int, DNAStrand>()
        // add a black strand by default, other colors will get added in
        // the loop
        val blackStrand = DNAStrand()
        blackStrand.color = CONFLICT_COLOR
        strands.put(CONFLICT_COLOR, blackStrand)
        // the min length is the number of minutes that will occupy
        // MIN_SEGMENT_PIXELS in the 'work day' time slot. This computes the
        // minutes/pixel * minpx where the number of pixels are 3/4 the total
        // dna height: 4*(mins/(px * 3/4))
        val minMinutes = minPixels * 4 * WORK_DAY_MINUTES / (3 * (bottom - top))

        // There are slightly fewer than half as many pixels in 1/6 the space,
        // so round to 2.5x for the min minutes in the non-work area
        val minOtherMinutes = minMinutes * 5 / 2
        val lastJulianDay = firstJulianDay + dayXs.size - 1
        val event = Event()
        // Go through all the events for the week
        for (currEvent in events) {
            // if this event is outside the weeks range skip it
            if (currEvent != null &&
                (currEvent.endDay < firstJulianDay || currEvent.startDay > lastJulianDay)) {
                continue
            }
            if (currEvent?.drawAsAllday() == true) {
                addAllDayToStrands(currEvent, strands, firstJulianDay, dayXs.size)
                continue
            }
            // Copy the event over so we can clip its start and end to our range
            currEvent?.copyTo(event)
            if (event.startDay < firstJulianDay) {
                event.startDay = firstJulianDay
                event.startTime = 0
            }
            // If it starts after the work day make sure the start is at least
            // minPixels from midnight
            if (event.startTime > DAY_IN_MINUTES - minOtherMinutes) {
                event.startTime = DAY_IN_MINUTES - minOtherMinutes
            }
            if (event.endDay > lastJulianDay) {
                event.endDay = lastJulianDay
                event.endTime = DAY_IN_MINUTES - 1
            }
            // If the end time is before the work day make sure it ends at least
            // minPixels after midnight
            if (event.endTime < minOtherMinutes) {
                event.endTime = minOtherMinutes
            }
            // If the start and end are on the same day make sure they are at
            // least minPixels apart. This only needs to be done for times
            // outside the work day as the min distance for within the work day
            // is enforced in the segment code.
            if (event.startDay === event.endDay &&
                event.endTime - event.startTime < minOtherMinutes
            ) {
                // If it's less than minPixels in an area before the work
                // day
                if (event.startTime < WORK_DAY_START_MINUTES) {
                    // extend the end to the first easy guarantee that it's
                    // minPixels
                    event.endTime = Math.min(
                        event.startTime + minOtherMinutes,
                        WORK_DAY_START_MINUTES + minMinutes
                    )
                    // if it's in the area after the work day
                } else if (event.endTime > WORK_DAY_END_MINUTES) {
                    // First try shifting the end but not past midnight
                    event.endTime = Math.min(event.endTime + minOtherMinutes, DAY_IN_MINUTES - 1)
                    // if it's still too small move the start back
                    if (event.endTime - event.startTime < minOtherMinutes) {
                        event.startTime = event.endTime - minOtherMinutes
                    }
                }
            }

            // This handles adding the first segment
            if (segments.size == 0) {
                addNewSegment(segments, event, strands, firstJulianDay, 0, minMinutes)
                continue
            }
            // Now compare our current start time to the end time of the last
            // segment in the list
            val lastSegment: DNASegment = segments.getLast()
            var startMinute: Int =
                (event.startDay - firstJulianDay) * DAY_IN_MINUTES + event.startTime
            var endMinute: Int = Math.max(
                (event.endDay - firstJulianDay) * DAY_IN_MINUTES +
                    event.endTime, startMinute + minMinutes
            )
            if (startMinute < 0) {
                startMinute = 0
            }
            if (endMinute >= WEEK_IN_MINUTES) {
                endMinute = WEEK_IN_MINUTES - 1
            }
            // If we start before the last segment in the list ends we need to
            // start going through the list as this may conflict with other
            // events
            if (startMinute < lastSegment.endMinute) {
                var i: Int = segments.size
                // find the last segment this event intersects with
                while (--i >= 0 && endMinute < segments.get(i).startMinute) {}

                var currSegment: DNASegment = DNASegment()
                // for each segment this event intersects with
                while (i >= 0 && startMinute <= segments.get(i)
                        .also { currSegment = it }.endMinute) {

                    // if the segment is already a conflict ignore it
                    if (currSegment.color == CONFLICT_COLOR) {
                        i--
                        continue
                    }
                    // if the event ends before the segment and wouldn't create
                    // a segment that is too small split off the right side
                    if (endMinute < currSegment.endMinute - minMinutes) {
                        val rhs = DNASegment()
                        rhs.endMinute = currSegment.endMinute
                        rhs.color = currSegment.color
                        rhs.startMinute = endMinute + 1
                        rhs.day = currSegment.day
                        currSegment.endMinute = endMinute
                        segments.add(i + 1, rhs)
                        // Equivalent to strands.get(rhs.color)?.count++
                        // but there is no null safe invocation for ++
                        strands.get(rhs.color)?.count = strands.get(rhs.color)?.count?.inc() as Int
                        if (DEBUG) {
                            Log.d(
                                TAG, "Added rhs, curr:" + currSegment.toString() + " i:" +
                                    segments.get(i).toString()
                            )
                        }
                    }
                    // if the event starts after the segment and wouldn't create
                    // a segment that is too small split off the left side
                    if (startMinute > currSegment.startMinute + minMinutes) {
                        val lhs = DNASegment()
                        lhs.startMinute = currSegment.startMinute
                        lhs.color = currSegment.color
                        lhs.endMinute = startMinute - 1
                        lhs.day = currSegment.day
                        currSegment.startMinute = startMinute
                        // increment i so that we are at the right position when
                        // referencing the segments to the right and left of the
                        // current segment.
                        segments.add(i++, lhs)
                        strands.get(lhs.color)?.count = strands.get(lhs.color)?.count?.inc() as Int
                        if (DEBUG) {
                            Log.d(
                                TAG, "Added lhs, curr:" + currSegment.toString() + " i:" +
                                    segments.get(i).toString()
                            )
                        }
                    }
                    // if the right side is black merge this with the segment to
                    // the right if they're on the same day and overlap
                    if (i + 1 < segments.size) {
                        val rhs: DNASegment = segments.get(i + 1)
                        if (rhs.color == CONFLICT_COLOR && currSegment.day == rhs.day &&
                            rhs.startMinute <= currSegment.endMinute + 1) {
                            rhs.startMinute = Math.min(currSegment.startMinute, rhs.startMinute)
                            segments.remove(currSegment)
                            strands.get(currSegment.color)?.count =
                                strands.get(currSegment.color)?.count?.dec() as Int
                            // point at the new current segment
                            currSegment = rhs
                        }
                    }
                    // if the left side is black merge this with the segment to
                    // the left if they're on the same day and overlap
                    if (i - 1 >= 0) {
                        val lhs: DNASegment = segments.get(i - 1)
                        if (lhs.color == CONFLICT_COLOR && currSegment.day == lhs.day &&
                            lhs.endMinute >= currSegment.startMinute - 1) {
                            lhs.endMinute = Math.max(currSegment.endMinute, lhs.endMinute)
                            segments.remove(currSegment)
                            strands.get(currSegment.color)?.count =
                                strands.get(currSegment.color)?.count?.dec() as Int
                            // point at the new current segment
                            currSegment = lhs
                            // point i at the new current segment in case new
                            // code is added
                            i--
                        }
                    }
                    // if we're still not black, decrement the count for the
                    // color being removed, change this to black, and increment
                    // the black count
                    if (currSegment.color != CONFLICT_COLOR) {
                        strands.get(currSegment.color)?.count =
                            strands.get(currSegment.color)?.count?.dec() as Int
                        currSegment.color = CONFLICT_COLOR
                        strands.get(CONFLICT_COLOR)?.count =
                            strands.get(CONFLICT_COLOR)?.count?.inc() as Int
                    }
                    i--
                }
            }
            // If this event extends beyond the last segment add a new segment
            if (endMinute > lastSegment.endMinute) {
                addNewSegment(
                    segments, event, strands, firstJulianDay, lastSegment.endMinute,
                    minMinutes
                )
            }
        }
        weaveDNAStrands(segments, firstJulianDay, strands, top, bottom, dayXs)
        return strands
    }

    // This figures out allDay colors as allDay events are found
    private fun addAllDayToStrands(
        event: Event?,
        strands: HashMap<Int, DNAStrand>,
        firstJulianDay: Int,
        numDays: Int
    ) {
        val strand = getOrCreateStrand(strands, CONFLICT_COLOR)
        // if we haven't initialized the allDay portion create it now
        if (strand?.allDays == null) {
            strand?.allDays = IntArray(numDays)
        }

        // For each day this event is on update the color
        val end: Int = Math.min((event?.endDay ?: 0) - firstJulianDay, numDays - 1)
        for (i in Math.max((event?.startDay ?: 0) - firstJulianDay, 0)..end) {
            if (strand?.allDays!![i] != 0) {
                // if this day already had a color, it is now a conflict
                strand?.allDays!![i] = CONFLICT_COLOR
            } else {
                // else it's just the color of the event
                strand?.allDays!![i] = event?.color as Int
            }
        }
    }

    // This processes all the segments, sorts them by color, and generates a
    // list of points to draw
    private fun weaveDNAStrands(
        segments: LinkedList<DNASegment>,
        firstJulianDay: Int,
        strands: HashMap<Int, DNAStrand>,
        top: Int,
        bottom: Int,
        dayXs: IntArray
    ) {
        // First, get rid of any colors that ended up with no segments
        val strandIterator = strands.values.iterator()
        while (strandIterator.hasNext()) {
            val strand = strandIterator.next()
            if (strand?.count < 1 && strand.allDays == null) {
                strandIterator.remove()
                continue
            }
            strand.points = FloatArray(strand.count * 4)
            strand.position = 0
        }
        // Go through each segment and compute its points
        for (segment in segments) {
            // Add the points to the strand of that color
            val strand: DNAStrand? = strands.get(segment.color)
            val dayIndex = segment.day - firstJulianDay
            val dayStartMinute = segment.startMinute % DAY_IN_MINUTES
            val dayEndMinute = segment.endMinute % DAY_IN_MINUTES
            val height = bottom - top
            val workDayHeight = height * 3 / 4
            val remainderHeight = (height - workDayHeight) / 2
            val x = dayXs[dayIndex]
            var y0 = 0
            var y1 = 0
            y0 = top + getPixelOffsetFromMinutes(dayStartMinute, workDayHeight, remainderHeight)
            y1 = top + getPixelOffsetFromMinutes(dayEndMinute, workDayHeight, remainderHeight)
            if (DEBUG) {
                Log.d(
                    TAG,
                    "Adding " + Integer.toHexString(segment.color).toString() + " at x,y0,y1: " + x
                        .toString() + " " + y0.toString() + " " + y1.toString() +
                        " for " + dayStartMinute.toString() + " " + dayEndMinute
                )
            }
            strand?.points!![strand?.position] = x.toFloat()
            strand?.position = strand?.position?.inc() as Int

            strand?.points!![strand?.position] = y0.toFloat()
            strand?.position = strand?.position?.inc() as Int

            strand?.points!![strand?.position] = x.toFloat()
            strand?.position = strand?.position.inc() as Int

            strand?.points!![strand?.position] = y1.toFloat()
            strand?.position = strand?.position.inc() as Int
        }
    }

    /**
     * Compute a pixel offset from the top for a given minute from the work day
     * height and the height of the top area.
     */
    private fun getPixelOffsetFromMinutes(
        minute: Int,
        workDayHeight: Int,
        remainderHeight: Int
    ): Int {
        val y: Int
        if (minute < WORK_DAY_START_MINUTES) {
            y = minute * remainderHeight / WORK_DAY_START_MINUTES
        } else if (minute < WORK_DAY_END_MINUTES) {
            y = remainderHeight + (minute - WORK_DAY_START_MINUTES) *
                workDayHeight / WORK_DAY_MINUTES
        } else {
            y = remainderHeight + workDayHeight +
                (minute - WORK_DAY_END_MINUTES) * remainderHeight / WORK_DAY_END_LENGTH
        }
        return y
    }

    /**
     * Add a new segment based on the event provided. This will handle splitting
     * segments across day boundaries and ensures a minimum size for segments.
     */
    private fun addNewSegment(
        segments: LinkedList<DNASegment>,
        event: Event,
        strands: HashMap<Int, DNAStrand>,
        firstJulianDay: Int,
        minStart: Int,
        minMinutes: Int
    ) {
        var event: Event = event
        var minStart = minStart
        if (event.startDay > event.endDay) {
            Log.wtf(TAG, "Event starts after it ends: " + event.toString())
        }
        // If this is a multiday event split it up by day
        if (event.startDay !== event.endDay) {
            val lhs = Event()
            lhs.color = event.color
            lhs.startDay = event.startDay
            // the first day we want the start time to be the actual start time
            lhs.startTime = event.startTime
            lhs.endDay = lhs.startDay
            lhs.endTime = DAY_IN_MINUTES - 1
            // Nearly recursive iteration!
            while (lhs.startDay !== event.endDay) {
                addNewSegment(segments, lhs, strands, firstJulianDay, minStart, minMinutes)
                // The days in between are all day, even though that shouldn't
                // actually happen due to the allday filtering
                lhs.startDay++
                lhs.endDay = lhs.startDay
                lhs.startTime = 0
                minStart = 0
            }
            // The last day we want the end time to be the actual end time
            lhs.endTime = event.endTime
            event = lhs
        }
        // Create the new segment and compute its fields
        val segment = DNASegment()
        val dayOffset: Int = (event.startDay - firstJulianDay) * DAY_IN_MINUTES
        val endOfDay = dayOffset + DAY_IN_MINUTES - 1
        // clip the start if needed
        segment.startMinute = Math.max(dayOffset + event.startTime, minStart)
        // and extend the end if it's too small, but not beyond the end of the
        // day
        val minEnd: Int = Math.min(segment.startMinute + minMinutes, endOfDay)
        segment.endMinute = Math.max(dayOffset + event.endTime, minEnd)
        if (segment.endMinute > endOfDay) {
            segment.endMinute = endOfDay
        }
        segment.color = event.color
        segment.day = event.startDay
        segments.add(segment)
        // increment the count for the correct color or add a new strand if we
        // don't have that color yet
        val strand = getOrCreateStrand(strands, segment.color)
        strand?.count
        strand?.count = strand?.count?.inc() as Int
    }

    /**
     * Try to get a strand of the given color. Create it if it doesn't exist.
     */
    private fun getOrCreateStrand(strands: HashMap<Int, DNAStrand>, color: Int): DNAStrand? {
        var strand: DNAStrand? = strands.get(color)
        if (strand == null) {
            strand = DNAStrand()
            strand?.color = color
            strand?.count = 0
            strands?.put(strand?.color, strand)
        }
        return strand
    }

    /**
     * Sends an intent to launch the top level Calendar view.
     *
     * @param context
     */
    @JvmStatic fun returnToCalendarHome(context: Context) {
        val launchIntent = Intent(context, AllInOneActivity::class.java)
        launchIntent.setAction(Intent.ACTION_DEFAULT)
        launchIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        launchIntent.putExtra(INTENT_KEY_HOME, true)
        context.startActivity(launchIntent)
    }

    /**
     * Given a context and a time in millis since unix epoch figures out the
     * correct week of the year for that time.
     *
     * @param millisSinceEpoch
     * @return
     */
    @JvmStatic fun getWeekNumberFromTime(millisSinceEpoch: Long, context: Context?): Int {
        val weekTime = Time(getTimeZone(context, null))
        weekTime.set(millisSinceEpoch)
        weekTime.normalize(true)
        val firstDayOfWeek = getFirstDayOfWeek(context)
        // if the date is on Saturday or Sunday and the start of the week
        // isn't Monday we may need to shift the date to be in the correct
        // week
        if (weekTime.weekDay === Time.SUNDAY &&
            (firstDayOfWeek == Time.SUNDAY || firstDayOfWeek == Time.SATURDAY)
        ) {
            weekTime.monthDay++
            weekTime.normalize(true)
        } else if (weekTime.weekDay === Time.SATURDAY && firstDayOfWeek == Time.SATURDAY) {
            weekTime.monthDay += 2
            weekTime.normalize(true)
        }
        return weekTime.getWeekNumber()
    }

    /**
     * Formats a day of the week string. This is either just the name of the day
     * or a combination of yesterday/today/tomorrow and the day of the week.
     *
     * @param julianDay The julian day to get the string for
     * @param todayJulianDay The julian day for today's date
     * @param millis A utc millis since epoch time that falls on julian day
     * @param context The calling context, used to get the timezone and do the
     * formatting
     * @return
     */
    @JvmStatic fun getDayOfWeekString(
        julianDay: Int,
        todayJulianDay: Int,
        millis: Long,
        context: Context
    ): String {
        getTimeZone(context, null)
        val flags: Int = DateUtils.FORMAT_SHOW_WEEKDAY
        var dayViewText: String
        dayViewText = if (julianDay == todayJulianDay) {
            context.getString(
                R.string.agenda_today,
                mTZUtils?.formatDateRange(context, millis, millis, flags)
                    .toString()
            )
        } else if (julianDay == todayJulianDay - 1) {
            context.getString(
                R.string.agenda_yesterday,
                mTZUtils?.formatDateRange(context, millis, millis, flags)
                    .toString()
            )
        } else if (julianDay == todayJulianDay + 1) {
            context.getString(
                R.string.agenda_tomorrow,
                mTZUtils?.formatDateRange(context, millis, millis, flags)
                    .toString()
            )
        } else {
            mTZUtils?.formatDateRange(context, millis, millis, flags)
                .toString()
        }
        dayViewText = dayViewText.toUpperCase()
        return dayViewText
    }

    // Calculate the time until midnight + 1 second and set the handler to
    // do run the runnable
    @JvmStatic fun setMidnightUpdater(h: Handler?, r: Runnable?, timezone: String?) {
        if (h == null || r == null || timezone == null) {
            return
        }
        val now: Long = System.currentTimeMillis()
        val time = Time(timezone)
        time.set(now)
        val runInMillis: Long = ((24 * 3600 - time.hour * 3600 - time.minute * 60 -
            time.second + 1) * 1000).toLong()
        h.removeCallbacks(r)
        h.postDelayed(r, runInMillis)
    }

    // Stop the midnight update thread
    @JvmStatic fun resetMidnightUpdater(h: Handler?, r: Runnable?) {
        if (h == null || r == null) {
            return
        }
        h.removeCallbacks(r)
    }

    /**
     * Returns a string description of the specified time interval.
     */
    @JvmStatic fun getDisplayedDatetime(
        startMillis: Long,
        endMillis: Long,
        currentMillis: Long,
        localTimezone: String,
        allDay: Boolean,
        context: Context
    ): String? {
        // Configure date/time formatting.
        val flagsDate: Int = DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_WEEKDAY
        var flagsTime: Int = DateUtils.FORMAT_SHOW_TIME
        if (DateFormat.is24HourFormat(context)) {
            flagsTime = flagsTime or DateUtils.FORMAT_24HOUR
        }
        val currentTime = Time(localTimezone)
        currentTime.set(currentMillis)
        val resources: Resources = context.getResources()
        var datetimeString: String? = null
        if (allDay) {
            // All day events require special timezone adjustment.
            val localStartMillis = convertAlldayUtcToLocal(null, startMillis, localTimezone)
            val localEndMillis = convertAlldayUtcToLocal(null, endMillis, localTimezone)
            if (singleDayEvent(localStartMillis, localEndMillis, currentTime.gmtoff)) {
                // If possible, use "Today" or "Tomorrow" instead of a full date string.
                val todayOrTomorrow = isTodayOrTomorrow(
                    context.getResources(),
                    localStartMillis, currentMillis, currentTime.gmtoff
                )
                if (TODAY == todayOrTomorrow) {
                    datetimeString = resources.getString(R.string.today)
                } else if (TOMORROW == todayOrTomorrow) {
                    datetimeString = resources.getString(R.string.tomorrow)
                }
            }
            if (datetimeString == null) {
                // For multi-day allday events or single-day all-day events that are not
                // today or tomorrow, use framework formatter.
                val f = Formatter(StringBuilder(50), Locale.getDefault())
                datetimeString = DateUtils.formatDateRange(
                    context, f, startMillis,
                    endMillis, flagsDate, Time.TIMEZONE_UTC
                ).toString()
            }
        } else {
            datetimeString = if (singleDayEvent(startMillis, endMillis, currentTime.gmtoff)) {
                // Format the time.
                val timeString = formatDateRange(
                    context, startMillis, endMillis,
                    flagsTime
                )

                // If possible, use "Today" or "Tomorrow" instead of a full date string.
                val todayOrTomorrow = isTodayOrTomorrow(
                    context.getResources(), startMillis,
                    currentMillis, currentTime.gmtoff
                )
                if (TODAY == todayOrTomorrow) {
                    // Example: "Today at 1:00pm - 2:00 pm"
                    resources.getString(
                        R.string.today_at_time_fmt,
                        timeString
                    )
                } else if (TOMORROW == todayOrTomorrow) {
                    // Example: "Tomorrow at 1:00pm - 2:00 pm"
                    resources.getString(
                        R.string.tomorrow_at_time_fmt,
                        timeString
                    )
                } else {
                    // Format the full date. Example: "Thursday, April 12, 1:00pm - 2:00pm"
                    val dateString = formatDateRange(
                        context, startMillis, endMillis,
                        flagsDate
                    )
                    resources.getString(
                        R.string.date_time_fmt, dateString,
                        timeString
                    )
                }
            } else {
                // For multiday events, shorten day/month names.
                // Example format: "Fri Apr 6, 5:00pm - Sun, Apr 8, 6:00pm"
                val flagsDatetime = flagsDate or flagsTime or DateUtils.FORMAT_ABBREV_MONTH or
                    DateUtils.FORMAT_ABBREV_WEEKDAY
                formatDateRange(
                    context, startMillis, endMillis,
                    flagsDatetime
                )
            }
        }
        return datetimeString
    }

    /**
     * Returns the timezone to display in the event info, if the local timezone is different
     * from the event timezone.  Otherwise returns null.
     */
    @JvmStatic fun getDisplayedTimezone(
        startMillis: Long,
        localTimezone: String?,
        eventTimezone: String?
    ): String? {
        var tzDisplay: String? = null
        if (!TextUtils.equals(localTimezone, eventTimezone)) {
            // Figure out if this is in DST
            val tz: TimeZone = TimeZone.getTimeZone(localTimezone)
            tzDisplay = if (tz == null || tz.getID().equals("GMT")) {
                localTimezone
            } else {
                val startTime = Time(localTimezone)
                startTime.set(startMillis)
                tz.getDisplayName(startTime.isDst !== 0, TimeZone.SHORT)
            }
        }
        return tzDisplay
    }

    /**
     * Returns whether the specified time interval is in a single day.
     */
    private fun singleDayEvent(startMillis: Long, endMillis: Long, localGmtOffset: Long): Boolean {
        if (startMillis == endMillis) {
            return true
        }

        // An event ending at midnight should still be a single-day event, so check
        // time end-1.
        val startDay: Int = Time.getJulianDay(startMillis, localGmtOffset)
        val endDay: Int = Time.getJulianDay(endMillis - 1, localGmtOffset)
        return startDay == endDay
    }

    // Using int constants as a return value instead of an enum to minimize resources.
    private const val TODAY = 1
    private const val TOMORROW = 2
    private const val NONE = 0

    /**
     * Returns TODAY or TOMORROW if applicable.  Otherwise returns NONE.
     */
    private fun isTodayOrTomorrow(
        r: Resources,
        dayMillis: Long,
        currentMillis: Long,
        localGmtOffset: Long
    ): Int {
        val startDay: Int = Time.getJulianDay(dayMillis, localGmtOffset)
        val currentDay: Int = Time.getJulianDay(currentMillis, localGmtOffset)
        val days = startDay - currentDay
        return if (days == 1) {
            TOMORROW
        } else if (days == 0) {
            TODAY
        } else {
            NONE
        }
    }

    /**
     * Inserts a drawable with today's day into the today's icon in the option menu
     * @param icon - today's icon from the options menu
     */
    @JvmStatic fun setTodayIcon(icon: LayerDrawable, c: Context?, timezone: String?) {
        val today: DayOfMonthDrawable

        // Reuse current drawable if possible
        val currentDrawable: Drawable? = icon.findDrawableByLayerId(R.id.today_icon_day)
        if (currentDrawable != null && currentDrawable is DayOfMonthDrawable) {
            today = currentDrawable as DayOfMonthDrawable
        } else {
            today = DayOfMonthDrawable(c as Context)
        }
        // Set the day and update the icon
        val now = Time(timezone)
        now.setToNow()
        now.normalize(false)
        today.setDayOfMonth(now.monthDay)
        icon.mutate()
        icon.setDrawableByLayerId(R.id.today_icon_day, today)
    }

    /**
     * Get a list of quick responses used for emailing guests from the
     * SharedPreferences. If not are found, get the hard coded ones that shipped
     * with the app
     *
     * @param context
     * @return a list of quick responses.
     */
    fun getQuickResponses(context: Context): Array<String> {
        var s = getSharedPreference(context, KEY_QUICK_RESPONSES, null as Array<String>?)
        if (s == null) {
            s = context.getResources().getStringArray(R.array.quick_response_defaults)
        }
        return s
    }

    /**
     * Return the app version code.
     */
    fun getVersionCode(context: Context): String? {
        if (sVersion == null) {
            try {
                sVersion = context.getPackageManager().getPackageInfo(
                    context.getPackageName(), 0
                ).versionName
            } catch (e: PackageManager.NameNotFoundException) {
                // Can't find version; just leave it blank.
                Log.e(TAG, "Error finding package " + context.getApplicationInfo().packageName)
            }
        }
        return sVersion
    }

    // A single strand represents one color of events. Events are divided up by
    // color to make them convenient to draw. The black strand is special in
    // that it holds conflicting events as well as color settings for allday on
    // each day.
    class DNAStrand {
        @JvmField var points: FloatArray? = null
        @JvmField var allDays: IntArray? = null // color for the allday, 0 means no event
        @JvmField var position = 0
        @JvmField var color = 0
        @JvmField var count = 0
    }

    // A segment is a single continuous length of time occupied by a single
    // color. Segments should never span multiple days.
    private class DNASegment {
        var startMinute = 0 // in minutes since the start of the week =
        var endMinute = 0
        var color = 0 // Calendar color or black for conflicts =
        var day = 0 // quick reference to the day this segment is on =
    }
}