/*
 * 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 com.android.calendar.CalendarController.ViewType
import android.content.Context
import android.os.Handler
import android.text.format.DateUtils
import android.text.format.Time
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import java.util.Formatter
import java.util.Locale

/*
 * The MenuSpinnerAdapter defines the look of the ActionBar's pull down menu
 * for small screen layouts. The pull down menu replaces the tabs uses for big screen layouts
 *
 * The MenuSpinnerAdapter responsible for creating the views used for in the pull down menu.
 */
class CalendarViewAdapter(context: Context, viewType: Int, showDate: Boolean) : BaseAdapter() {
    private val mButtonNames: Array<String> // Text on buttons

    // Used to define the look of the menu button according to the current view:
    // Day view: show day of the week + full date underneath
    // Week view: show the month + year
    // Month view: show the month + year
    // Agenda view: show day of the week + full date underneath
    private var mCurrentMainView: Int
    private val mInflater: LayoutInflater

    // The current selected event's time, used to calculate the date and day of the week
    // for the buttons.
    private var mMilliTime: Long = 0
    private var mTimeZone: String? = null
    private var mTodayJulianDay: Long = 0
    private val mContext: Context = context
    private val mFormatter: Formatter
    private val mStringBuilder: StringBuilder
    private var mMidnightHandler: Handler? = null // Used to run a time update every midnight
    private val mShowDate: Boolean // Spinner mode indicator (view name or view name with date)

    // Updates time specific variables (time-zone, today's Julian day).
    private val mTimeUpdater: Runnable = object : Runnable {
        @Override
        override fun run() {
            refresh(mContext)
        }
    }

    // Sets the time zone and today's Julian day to be used by the adapter.
    // Also, notify listener on the change and resets the midnight update thread.
    fun refresh(context: Context?) {
        mTimeZone = Utils.getTimeZone(context, mTimeUpdater)
        val time = Time(mTimeZone)
        val now: Long = System.currentTimeMillis()
        time.set(now)
        mTodayJulianDay = Time.getJulianDay(now, time.gmtoff).toLong()
        notifyDataSetChanged()
        setMidnightHandler()
    }

    // Sets a thread to run 1 second after midnight and update the current date
    // This is used to display correctly the date of yesterday/today/tomorrow
    private fun setMidnightHandler() {
        mMidnightHandler?.removeCallbacks(mTimeUpdater)
        // Set the time updater to run at 1 second after midnight
        val now: Long = System.currentTimeMillis()
        val time = Time(mTimeZone)
        time.set(now)
        val runInMillis: Long = ((24 * 3600 - time.hour * 3600 - time.minute * 60 -
                time.second + 1) * 1000).toLong()
        mMidnightHandler?.postDelayed(mTimeUpdater, runInMillis)
    }

    // Stops the midnight update thread, called by the activity when it is paused.
    fun onPause() {
        mMidnightHandler?.removeCallbacks(mTimeUpdater)
    }

    // Returns the amount of buttons in the menu
    @Override
    override fun getCount(): Int {
        return mButtonNames.size
    }

    @Override
    override fun getItem(position: Int): Any? {
        return if (position < mButtonNames.size) {
            mButtonNames[position]
        } else null
    }

    @Override
    override fun getItemId(position: Int): Long {
        // Item ID is its location in the list
        return position.toLong()
    }

    @Override
    override fun hasStableIds(): Boolean {
        return false
    }

    @Override
    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
        var v: View?
        if (mShowDate) {
            // Check if can recycle the view
            if (convertView == null || (convertView.getTag() as Int)
                    != R.layout.actionbar_pulldown_menu_top_button as Int) {
                v = mInflater.inflate(R.layout.actionbar_pulldown_menu_top_button, parent, false)
                // Set the tag to make sure you can recycle it when you get it
                // as a convert view
                v.setTag(Integer(R.layout.actionbar_pulldown_menu_top_button))
            } else {
                v = convertView
            }
            val weekDay: TextView = v?.findViewById(R.id.top_button_weekday) as TextView
            val date: TextView = v?.findViewById(R.id.top_button_date) as TextView
            when (mCurrentMainView) {
                ViewType.DAY -> {
                    weekDay.setVisibility(View.VISIBLE)
                    weekDay.setText(buildDayOfWeek())
                    date.setText(buildFullDate())
                }
                ViewType.WEEK -> {
                    if (Utils.getShowWeekNumber(mContext)) {
                        weekDay.setVisibility(View.VISIBLE)
                        weekDay.setText(buildWeekNum())
                    } else {
                        weekDay.setVisibility(View.GONE)
                    }
                    date.setText(buildMonthYearDate())
                }
                ViewType.MONTH -> {
                    weekDay.setVisibility(View.GONE)
                    date.setText(buildMonthYearDate())
                }
                else -> v = null
            }
        } else {
            if (convertView == null || (convertView.getTag() as Int)
                    != R.layout.actionbar_pulldown_menu_top_button_no_date as Int) {
                v = mInflater.inflate(
                        R.layout.actionbar_pulldown_menu_top_button_no_date, parent, false)
                // Set the tag to make sure you can recycle it when you get it
                // as a convert view
                v.setTag(Integer(R.layout.actionbar_pulldown_menu_top_button_no_date))
            } else {
                v = convertView
            }
            val title: TextView? = v as TextView?
            when (mCurrentMainView) {
                ViewType.DAY -> title?.setText(mButtonNames[DAY_BUTTON_INDEX])
                ViewType.WEEK -> title?.setText(mButtonNames[WEEK_BUTTON_INDEX])
                ViewType.MONTH -> title?.setText(mButtonNames[MONTH_BUTTON_INDEX])
                else -> v = null
            }
        }
        return v
    }

    @Override
    override fun getItemViewType(position: Int): Int {
        // Only one kind of view is used
        return BUTTON_VIEW_TYPE
    }

    @Override
    override fun getViewTypeCount(): Int {
        return VIEW_TYPE_NUM
    }

    @Override
    override fun isEmpty(): Boolean {
        return mButtonNames.size == 0
    }

    @Override
    override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup?): View? {
        var v: View? = mInflater.inflate(R.layout.actionbar_pulldown_menu_button, parent, false)
        val viewType: TextView? = v?.findViewById(R.id.button_view) as? TextView
        val date: TextView? = v?.findViewById(R.id.button_date) as? TextView
        when (position) {
            DAY_BUTTON_INDEX -> {
                viewType?.setText(mButtonNames[DAY_BUTTON_INDEX])
                if (mShowDate) {
                    date?.setText(buildMonthDayDate())
                }
            }
            WEEK_BUTTON_INDEX -> {
                viewType?.setText(mButtonNames[WEEK_BUTTON_INDEX])
                if (mShowDate) {
                    date?.setText(buildWeekDate())
                }
            }
            MONTH_BUTTON_INDEX -> {
                viewType?.setText(mButtonNames[MONTH_BUTTON_INDEX])
                if (mShowDate) {
                    date?.setText(buildMonthDate())
                }
            }
            else -> v = convertView
        }
        return v
    }

    // Updates the current viewType
    // Used to match the label on the menu button with the calendar view
    fun setMainView(viewType: Int) {
        mCurrentMainView = viewType
        notifyDataSetChanged()
    }

    // Update the date that is displayed on buttons
    // Used when the user selects a new day/week/month to watch
    fun setTime(time: Long) {
        mMilliTime = time
        notifyDataSetChanged()
    }

    // Builds a string with the day of the week and the word yesterday/today/tomorrow
    // before it if applicable.
    private fun buildDayOfWeek(): String {
        val t = Time(mTimeZone)
        t.set(mMilliTime)
        val julianDay: Long = Time.getJulianDay(mMilliTime, t.gmtoff).toLong()
        var dayOfWeek: String? = null
        mStringBuilder.setLength(0)
        dayOfWeek = if (julianDay == mTodayJulianDay) {
            mContext.getString(R.string.agenda_today,
                    DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
                            DateUtils.FORMAT_SHOW_WEEKDAY, mTimeZone).toString())
        } else if (julianDay == mTodayJulianDay - 1) {
            mContext.getString(R.string.agenda_yesterday,
                    DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
                            DateUtils.FORMAT_SHOW_WEEKDAY, mTimeZone).toString())
        } else if (julianDay == mTodayJulianDay + 1) {
            mContext.getString(R.string.agenda_tomorrow,
                    DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
                            DateUtils.FORMAT_SHOW_WEEKDAY, mTimeZone).toString())
        } else {
            DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
                    DateUtils.FORMAT_SHOW_WEEKDAY, mTimeZone).toString()
        }
        return dayOfWeek.toUpperCase()
    }

    // Builds strings with different formats:
    // Full date: Month,day Year
    // Month year
    // Month day
    // Month
    // Week:  month day-day or month day - month day
    private fun buildFullDate(): String {
        mStringBuilder.setLength(0)
        return DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
                DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_YEAR, mTimeZone).toString()
    }

    private fun buildMonthYearDate(): String {
        mStringBuilder.setLength(0)
        return DateUtils.formatDateRange(
                mContext,
                mFormatter,
                mMilliTime,
                mMilliTime,
                DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_MONTH_DAY
                        or DateUtils.FORMAT_SHOW_YEAR, mTimeZone).toString()
    }

    private fun buildMonthDayDate(): String {
        mStringBuilder.setLength(0)
        return DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
                DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR, mTimeZone).toString()
    }

    private fun buildMonthDate(): String {
        mStringBuilder.setLength(0)
        return DateUtils.formatDateRange(
                mContext,
                mFormatter,
                mMilliTime,
                mMilliTime,
                DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR
                        or DateUtils.FORMAT_NO_MONTH_DAY, mTimeZone).toString()
    }

    private fun buildWeekDate(): String {
        // Calculate the start of the week, taking into account the "first day of the week"
        // setting.
        val t = Time(mTimeZone)
        t.set(mMilliTime)
        val firstDayOfWeek: Int = Utils.getFirstDayOfWeek(mContext)
        val dayOfWeek: Int = t.weekDay
        var diff = dayOfWeek - firstDayOfWeek
        if (diff != 0) {
            if (diff < 0) {
                diff += 7
            }
            t.monthDay -= diff
            t.normalize(true /* ignore isDst */)
        }
        val weekStartTime: Long = t.toMillis(true)
        // The end of the week is 6 days after the start of the week
        val weekEndTime: Long = weekStartTime + DateUtils.WEEK_IN_MILLIS - DateUtils.DAY_IN_MILLIS

        // If week start and end is in 2 different months, use short months names
        val t1 = Time(mTimeZone)
        t.set(weekEndTime)
        var flags: Int = DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR
        if (t.month !== t1.month) {
            flags = flags or DateUtils.FORMAT_ABBREV_MONTH
        }
        mStringBuilder.setLength(0)
        return DateUtils.formatDateRange(mContext, mFormatter, weekStartTime,
                weekEndTime, flags, mTimeZone).toString()
    }

    private fun buildWeekNum(): String {
        val week: Int = Utils.getWeekNumberFromTime(mMilliTime, mContext)
        return mContext.getResources().getQuantityString(R.plurals.weekN, week, week)
    }

    companion object {
        private const val TAG = "MenuSpinnerAdapter"

        // Defines the types of view returned by this spinner
        private const val BUTTON_VIEW_TYPE = 0
        const val VIEW_TYPE_NUM = 1 // Increase this if you add more view types
        const val DAY_BUTTON_INDEX = 0
        const val WEEK_BUTTON_INDEX = 1
        const val MONTH_BUTTON_INDEX = 2
        const val AGENDA_BUTTON_INDEX = 3
    }

    init {
        mMidnightHandler = Handler()
        mCurrentMainView = viewType
        mShowDate = showDate

        // Initialize
        mButtonNames = context.getResources().getStringArray(R.array.buttons_list)
        mInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        mStringBuilder = StringBuilder(50)
        mFormatter = Formatter(mStringBuilder, Locale.getDefault())

        // Sets time specific variables and starts a thread for midnight updates
        if (showDate) {
            refresh(context)
        }
    }
}