/*
 * Copyright (C) 2020 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.alarmclock

import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_NO_CREATE
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT
import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH
import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT
import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.Intent.ACTION_DATE_CHANGED
import android.content.Intent.ACTION_LOCALE_CHANGED
import android.content.Intent.ACTION_SCREEN_ON
import android.content.Intent.ACTION_TIMEZONE_CHANGED
import android.content.Intent.ACTION_TIME_CHANGED
import android.content.res.Resources
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import android.text.format.DateFormat
import android.util.ArraySet
import android.util.TypedValue.COMPLEX_UNIT_PX
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.View.MeasureSpec.UNSPECIFIED
import android.view.View.VISIBLE
import android.widget.RemoteViews
import android.widget.TextClock
import android.widget.TextView

import com.android.deskclock.DeskClock
import com.android.deskclock.LogUtils
import com.android.deskclock.R
import com.android.deskclock.Utils
import com.android.deskclock.alarms.AlarmStateManager
import com.android.deskclock.data.DataModel
import com.android.deskclock.uidata.UiDataModel
import com.android.deskclock.worldclock.CitySelectionActivity

import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.TimeZone

/**
 * This provider produces a widget resembling one of the formats below.
 *
 * If an alarm is scheduled to ring in the future:
 * <pre>
 *      12:59 AM
 *      WED, FEB 3 ⏰ THU 9:30 AM
 * </pre>
 *
 * If no alarm is scheduled to ring in the future:
 * <pre>
 *      12:59 AM
 *      WED, FEB 3
 * </pre>
 *
 * This widget is scaling the font sizes to fit within the widget bounds chosen by the user without
 * any clipping. To do so it measures layouts offscreen using a range of font sizes in order to
 * choose optimal values.
 */
class DigitalAppWidgetProvider : AppWidgetProvider() {

    override fun onEnabled(context: Context) {
        super.onEnabled(context)

        // Schedule the day-change callback if necessary.
        updateDayChangeCallback(context)
    }

    override fun onDisabled(context: Context) {
        super.onDisabled(context)

        // Remove any scheduled day-change callback.
        removeDayChangeCallback(context)
    }

    override fun onReceive(context: Context, intent: Intent) {
        LOGGER.i("onReceive: $intent")
        super.onReceive(context, intent)

        val wm: AppWidgetManager = AppWidgetManager.getInstance(context) ?: return

        val provider = ComponentName(context, javaClass)
        val widgetIds: IntArray = wm.getAppWidgetIds(provider)

        val action: String? = intent.action
        when (action) {
            ACTION_NEXT_ALARM_CLOCK_CHANGED,
            ACTION_DATE_CHANGED,
            ACTION_LOCALE_CHANGED,
            ACTION_SCREEN_ON,
            ACTION_TIME_CHANGED,
            ACTION_TIMEZONE_CHANGED,
            AlarmStateManager.ACTION_ALARM_CHANGED,
            ACTION_ON_DAY_CHANGE,
            DataModel.ACTION_WORLD_CITIES_CHANGED -> widgetIds.forEach { widgetId ->
                relayoutWidget(context, wm, widgetId, wm.getAppWidgetOptions(widgetId))
            }
        }

        val dm = DataModel.getDataModel()
        dm.updateWidgetCount(javaClass, widgetIds.size, R.string.category_digital_widget)

        if (widgetIds.size > 0) {
            updateDayChangeCallback(context)
        }
    }

    /**
     * Called when widgets must provide remote views.
     */
    override fun onUpdate(context: Context, wm: AppWidgetManager, widgetIds: IntArray) {
        super.onUpdate(context, wm, widgetIds)

        widgetIds.forEach { widgetId ->
            relayoutWidget(context, wm, widgetId, wm.getAppWidgetOptions(widgetId))
        }
    }

    /**
     * Called when the app widget changes sizes.
     */
    override fun onAppWidgetOptionsChanged(
        context: Context,
        wm: AppWidgetManager?,
        widgetId: Int,
        options: Bundle
    ) {
        super.onAppWidgetOptionsChanged(context, wm, widgetId, options)

        // Scale the fonts of the clock to fit inside the new size
        relayoutWidget(context, AppWidgetManager.getInstance(context), widgetId, options)
    }

    /**
     * Remove the existing day-change callback if it is not needed (no selected cities exist).
     * Add the day-change callback if it is needed (selected cities exist).
     */
    private fun updateDayChangeCallback(context: Context) {
        val dm = DataModel.getDataModel()
        val selectedCities = dm.selectedCities
        val showHomeClock = dm.showHomeClock
        if (selectedCities.isEmpty() && !showHomeClock) {
            // Remove the existing day-change callback.
            removeDayChangeCallback(context)
            return
        }

        // Look up the time at which the next day change occurs across all timezones.
        val zones: MutableSet<TimeZone> = ArraySet(selectedCities.size + 2)
        zones.add(TimeZone.getDefault())
        if (showHomeClock) {
            zones.add(dm.homeCity.timeZone)
        }
        selectedCities.forEach { city ->
            zones.add(city.timeZone)
        }
        val nextDay = Utils.getNextDay(Date(), zones)

        // Schedule the next day-change callback; at least one city is displayed.
        val pi: PendingIntent =
                PendingIntent.getBroadcast(context, 0, DAY_CHANGE_INTENT, FLAG_UPDATE_CURRENT)
        getAlarmManager(context).setExact(AlarmManager.RTC, nextDay.time, pi)
    }

    /**
     * Remove the existing day-change callback.
     */
    private fun removeDayChangeCallback(context: Context) {
        val pi: PendingIntent? =
                PendingIntent.getBroadcast(context, 0, DAY_CHANGE_INTENT, FLAG_NO_CREATE)
        if (pi != null) {
            getAlarmManager(context).cancel(pi)
            pi.cancel()
        }
    }

    /**
     * This class stores the target size of the widget as well as the measured size using a given
     * clock font size. All other fonts and icons are scaled proportional to the clock font.
     */
    private class Sizes(
        val mTargetWidthPx: Int,
        val mTargetHeightPx: Int,
        val largestClockFontSizePx: Int
    ) {
        val smallestClockFontSizePx = 1
        var mIconBitmap: Bitmap? = null

        var mMeasuredWidthPx = 0
        var mMeasuredHeightPx = 0
        var mMeasuredTextClockWidthPx = 0
        var mMeasuredTextClockHeightPx = 0

        /** The size of the font to use on the date / next alarm time fields.  */
        var mFontSizePx = 0

        /** The size of the font to use on the clock field.  */
        var mClockFontSizePx = 0

        var mIconFontSizePx = 0
        var mIconPaddingPx = 0

        var clockFontSizePx: Int
            get() = mClockFontSizePx
            set(clockFontSizePx) {
                mClockFontSizePx = clockFontSizePx
                mFontSizePx = Math.max(1, Math.round(clockFontSizePx / 7.5f))
                mIconFontSizePx = (mFontSizePx * 1.4f).toInt()
                mIconPaddingPx = mFontSizePx / 3
            }

        /**
         * @return the amount of widget height available to the world cities list
         */
        val listHeight: Int
            get() = mTargetHeightPx - mMeasuredHeightPx

        fun hasViolations(): Boolean {
            return mMeasuredWidthPx > mTargetWidthPx || mMeasuredHeightPx > mTargetHeightPx
        }

        fun newSize(): Sizes {
            return Sizes(mTargetWidthPx, mTargetHeightPx, largestClockFontSizePx)
        }

        override fun toString(): String {
            val builder = StringBuilder(1000)
            builder.append("\n")
            append(builder, "Target dimensions: %dpx x %dpx\n", mTargetWidthPx, mTargetHeightPx)
            append(builder, "Last valid widget container measurement: %dpx x %dpx\n",
                    mMeasuredWidthPx, mMeasuredHeightPx)
            append(builder, "Last text clock measurement: %dpx x %dpx\n",
                    mMeasuredTextClockWidthPx, mMeasuredTextClockHeightPx)
            if (mMeasuredWidthPx > mTargetWidthPx) {
                append(builder, "Measured width %dpx exceeded widget width %dpx\n",
                        mMeasuredWidthPx, mTargetWidthPx)
            }
            if (mMeasuredHeightPx > mTargetHeightPx) {
                append(builder, "Measured height %dpx exceeded widget height %dpx\n",
                        mMeasuredHeightPx, mTargetHeightPx)
            }
            append(builder, "Clock font: %dpx\n", mClockFontSizePx)
            return builder.toString()
        }

        companion object {
            private fun append(builder: StringBuilder, format: String, vararg args: Any) {
                builder.append(String.format(Locale.ENGLISH, format, *args))
            }
        }
    }

    companion object {
        private val LOGGER = LogUtils.Logger("DigitalWidgetProvider")

        /**
         * Intent action used for refreshing a world city display when any of them changes days or when
         * the default TimeZone changes days. This affects the widget display because the day-of-week is
         * only visible when the world city day-of-week differs from the default TimeZone's day-of-week.
         */
        private const val ACTION_ON_DAY_CHANGE = "com.android.deskclock.ON_DAY_CHANGE"

        /** Intent used to deliver the [.ACTION_ON_DAY_CHANGE] callback.  */
        private val DAY_CHANGE_INTENT: Intent = Intent(ACTION_ON_DAY_CHANGE)

        /**
         * Compute optimal font and icon sizes offscreen for both portrait and landscape orientations
         * using the last known widget size and apply them to the widget.
         */
        private fun relayoutWidget(
            context: Context,
            wm: AppWidgetManager,
            widgetId: Int,
            options: Bundle
        ) {
            val portrait: RemoteViews = relayoutWidget(context, wm, widgetId, options, true)
            val landscape: RemoteViews = relayoutWidget(context, wm, widgetId, options, false)
            val widget = RemoteViews(landscape, portrait)
            wm.updateAppWidget(widgetId, widget)
            wm.notifyAppWidgetViewDataChanged(widgetId, R.id.world_city_list)
        }

        /**
         * Compute optimal font and icon sizes offscreen for the given orientation.
         */
        private fun relayoutWidget(
            context: Context,
            wm: AppWidgetManager,
            widgetId: Int,
            options: Bundle?,
            portrait: Boolean
        ): RemoteViews {
            // Create a remote view for the digital clock.
            val packageName: String = context.getPackageName()
            val rv = RemoteViews(packageName, R.layout.digital_widget)

            // Tapping on the widget opens the app (if not on the lock screen).
            if (Utils.isWidgetClickable(wm, widgetId)) {
                val openApp = Intent(context, DeskClock::class.java)
                val pi: PendingIntent = PendingIntent.getActivity(context, 0, openApp, 0)
                rv.setOnClickPendingIntent(R.id.digital_widget, pi)
            }

            // Configure child views of the remote view.
            val dateFormat: CharSequence = getDateFormat(context)
            rv.setCharSequence(R.id.date, "setFormat12Hour", dateFormat)
            rv.setCharSequence(R.id.date, "setFormat24Hour", dateFormat)

            val nextAlarmTime = Utils.getNextAlarm(context)
            if (TextUtils.isEmpty(nextAlarmTime)) {
                rv.setViewVisibility(R.id.nextAlarm, GONE)
                rv.setViewVisibility(R.id.nextAlarmIcon, GONE)
            } else {
                rv.setTextViewText(R.id.nextAlarm, nextAlarmTime)
                rv.setViewVisibility(R.id.nextAlarm, VISIBLE)
                rv.setViewVisibility(R.id.nextAlarmIcon, VISIBLE)
            }

            val options = options ?: wm.getAppWidgetOptions(widgetId)

            // Fetch the widget size selected by the user.
            val resources: Resources = context.getResources()
            val density: Float = resources.getDisplayMetrics().density
            val minWidthPx = (density * options.getInt(OPTION_APPWIDGET_MIN_WIDTH)).toInt()
            val minHeightPx = (density * options.getInt(OPTION_APPWIDGET_MIN_HEIGHT)).toInt()
            val maxWidthPx = (density * options.getInt(OPTION_APPWIDGET_MAX_WIDTH)).toInt()
            val maxHeightPx = (density * options.getInt(OPTION_APPWIDGET_MAX_HEIGHT)).toInt()
            val targetWidthPx = if (portrait) minWidthPx else maxWidthPx
            val targetHeightPx = if (portrait) maxHeightPx else minHeightPx
            val largestClockFontSizePx: Int =
                    resources.getDimensionPixelSize(R.dimen.widget_max_clock_font_size)

            // Create a size template that describes the widget bounds.
            val template = Sizes(targetWidthPx, targetHeightPx, largestClockFontSizePx)

            // Compute optimal font sizes and icon sizes to fit within the widget bounds.
            val sizes = optimizeSizes(context, template, nextAlarmTime)
            if (LOGGER.isVerboseLoggable) {
                LOGGER.v(sizes.toString())
            }

            // Apply the computed sizes to the remote views.
            rv.setImageViewBitmap(R.id.nextAlarmIcon, sizes.mIconBitmap)
            rv.setTextViewTextSize(R.id.date, COMPLEX_UNIT_PX, sizes.mFontSizePx.toFloat())
            rv.setTextViewTextSize(R.id.nextAlarm, COMPLEX_UNIT_PX, sizes.mFontSizePx.toFloat())
            rv.setTextViewTextSize(R.id.clock, COMPLEX_UNIT_PX, sizes.mClockFontSizePx.toFloat())

            val smallestWorldCityListSizePx: Int =
                    resources.getDimensionPixelSize(R.dimen.widget_min_world_city_list_size)
            if (sizes.listHeight <= smallestWorldCityListSizePx) {
                // Insufficient space; hide the world city list.
                rv.setViewVisibility(R.id.world_city_list, GONE)
            } else {
                // Set an adapter on the world city list. That adapter connects to a Service via intent.
                val intent = Intent(context, DigitalAppWidgetCityService::class.java)
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId)
                intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)))
                rv.setRemoteAdapter(R.id.world_city_list, intent)
                rv.setViewVisibility(R.id.world_city_list, VISIBLE)

                // Tapping on the widget opens the city selection activity (if not on the lock screen).
                if (Utils.isWidgetClickable(wm, widgetId)) {
                    val selectCity = Intent(context, CitySelectionActivity::class.java)
                    val pi: PendingIntent = PendingIntent.getActivity(context, 0, selectCity, 0)
                    rv.setPendingIntentTemplate(R.id.world_city_list, pi)
                }
            }

            return rv
        }

        /**
         * Inflate an offscreen copy of the widget views. Binary search through the range of sizes until
         * the optimal sizes that fit within the widget bounds are located.
         */
        private fun optimizeSizes(context: Context, template: Sizes, nextAlarmTime: String): Sizes {
            // Inflate a test layout to compute sizes at different font sizes.
            val inflater: LayoutInflater = LayoutInflater.from(context)
            @SuppressLint("InflateParams") val sizer: View =
                    inflater.inflate(R.layout.digital_widget_sizer, null /* root */)

            // Configure the date to display the current date string.
            val dateFormat: CharSequence = getDateFormat(context)
            val date: TextClock = sizer.findViewById(R.id.date) as TextClock
            date.setFormat12Hour(dateFormat)
            date.setFormat24Hour(dateFormat)

            // Configure the next alarm views to display the next alarm time or be gone.
            val nextAlarmIcon: TextView = sizer.findViewById(R.id.nextAlarmIcon) as TextView
            val nextAlarm: TextView = sizer.findViewById(R.id.nextAlarm) as TextView
            if (TextUtils.isEmpty(nextAlarmTime)) {
                nextAlarm.setVisibility(GONE)
                nextAlarmIcon.setVisibility(GONE)
            } else {
                nextAlarm.setText(nextAlarmTime)
                nextAlarm.setVisibility(VISIBLE)
                nextAlarmIcon.setVisibility(VISIBLE)
                nextAlarmIcon.setTypeface(UiDataModel.getUiDataModel().alarmIconTypeface)
            }

            // Measure the widget at the largest possible size.
            var high = measure(template, template.largestClockFontSizePx, sizer)
            if (!high.hasViolations()) {
                return high
            }

            // Measure the widget at the smallest possible size.
            var low = measure(template, template.smallestClockFontSizePx, sizer)
            if (low.hasViolations()) {
                return low
            }

            // Binary search between the smallest and largest sizes until an optimum size is found.
            while (low.clockFontSizePx != high.clockFontSizePx) {
                val midFontSize: Int = (low.clockFontSizePx + high.clockFontSizePx) / 2
                if (midFontSize == low.clockFontSizePx) {
                    return low
                }
                val midSize = measure(template, midFontSize, sizer)
                if (midSize.hasViolations()) {
                    high = midSize
                } else {
                    low = midSize
                }
            }

            return low
        }

        private fun getAlarmManager(context: Context): AlarmManager {
            return context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        }

        /**
         * Compute all font and icon sizes based on the given `clockFontSize` and apply them to
         * the offscreen `sizer` view. Measure the `sizer` view and return the resulting
         * size measurements.
         */
        private fun measure(template: Sizes, clockFontSize: Int, sizer: View): Sizes {
            // Create a copy of the given template sizes.
            val measuredSizes = template.newSize()

            // Configure the clock to display the widest time string.
            val date: TextClock = sizer.findViewById(R.id.date) as TextClock
            val clock: TextClock = sizer.findViewById(R.id.clock) as TextClock
            val nextAlarm: TextView = sizer.findViewById(R.id.nextAlarm) as TextView
            val nextAlarmIcon: TextView = sizer.findViewById(R.id.nextAlarmIcon) as TextView

            // Adjust the font sizes.
            measuredSizes.clockFontSizePx = clockFontSize
            clock.setText(getLongestTimeString(clock))
            clock.setTextSize(COMPLEX_UNIT_PX, measuredSizes.mClockFontSizePx.toFloat())
            date.setTextSize(COMPLEX_UNIT_PX, measuredSizes.mFontSizePx.toFloat())
            nextAlarm.setTextSize(COMPLEX_UNIT_PX, measuredSizes.mFontSizePx.toFloat())
            nextAlarmIcon.setTextSize(COMPLEX_UNIT_PX, measuredSizes.mIconFontSizePx.toFloat())
            nextAlarmIcon
                    .setPadding(measuredSizes.mIconPaddingPx, 0, measuredSizes.mIconPaddingPx, 0)

            // Measure and layout the sizer.
            val widthSize: Int = View.MeasureSpec.getSize(measuredSizes.mTargetWidthPx)
            val heightSize: Int = View.MeasureSpec.getSize(measuredSizes.mTargetHeightPx)
            val widthMeasureSpec: Int = View.MeasureSpec.makeMeasureSpec(widthSize, UNSPECIFIED)
            val heightMeasureSpec: Int = View.MeasureSpec.makeMeasureSpec(heightSize, UNSPECIFIED)
            sizer.measure(widthMeasureSpec, heightMeasureSpec)
            sizer.layout(0, 0, sizer.getMeasuredWidth(), sizer.getMeasuredHeight())

            // Copy the measurements into the result object.
            measuredSizes.mMeasuredWidthPx = sizer.getMeasuredWidth()
            measuredSizes.mMeasuredHeightPx = sizer.getMeasuredHeight()
            measuredSizes.mMeasuredTextClockWidthPx = clock.getMeasuredWidth()
            measuredSizes.mMeasuredTextClockHeightPx = clock.getMeasuredHeight()

            // If an alarm icon is required, generate one from the TextView with the special font.
            if (nextAlarmIcon.getVisibility() == VISIBLE) {
                measuredSizes.mIconBitmap = Utils.createBitmap(nextAlarmIcon)
            }

            return measuredSizes
        }

        /**
         * @return "11:59" or "23:59" in the current locale
         */
        private fun getLongestTimeString(clock: TextClock): CharSequence {
            val format: CharSequence = if (clock.is24HourModeEnabled()) {
                clock.getFormat24Hour()
            } else {
                clock.getFormat12Hour()
            }
            val longestPMTime = Calendar.getInstance()
            longestPMTime[0, 0, 0, 23] = 59
            return DateFormat.format(format, longestPMTime)
        }

        /**
         * @return the locale-specific date pattern
         */
        private fun getDateFormat(context: Context): String {
            val locale = Locale.getDefault()
            val skeleton: String = context.getString(R.string.abbrev_wday_month_day_no_year)
            return DateFormat.getBestDateTimePattern(locale, skeleton)
        }
    }
}