/*
 * 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.deskclock.worldclock

import android.content.Context
import android.os.Bundle
import androidx.appcompat.widget.SearchView
import android.text.TextUtils
import android.text.format.DateFormat
import android.util.ArraySet
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.CheckBox
import android.widget.CompoundButton
import android.widget.ListView
import android.widget.SectionIndexer
import android.widget.TextView

import com.android.deskclock.BaseActivity
import com.android.deskclock.DropShadowController
import com.android.deskclock.R
import com.android.deskclock.Utils
import com.android.deskclock.actionbarmenu.MenuItemController
import com.android.deskclock.actionbarmenu.MenuItemControllerFactory
import com.android.deskclock.actionbarmenu.NavUpMenuItemController
import com.android.deskclock.actionbarmenu.OptionsMenuManager
import com.android.deskclock.actionbarmenu.SearchMenuItemController
import com.android.deskclock.actionbarmenu.SettingsMenuItemController
import com.android.deskclock.data.City
import com.android.deskclock.data.DataModel

import java.util.ArrayList
import java.util.Calendar
import java.util.Comparator
import java.util.Locale
import java.util.TimeZone

/**
 * This activity allows the user to alter the cities selected for display.
 *
 * Note, it is possible for two instances of this Activity to exist simultaneously:
 * <ul>
 * <li>Clock Tab-> Tap Floating Action Button</li>
 * <li>Digital Widget -> Tap any city clock</li>
 * </ul>
 *
 * As a result, [.onResume] conservatively refreshes itself from the backing
 * [DataModel] which may have changed since this activity was last displayed.
 */
class CitySelectionActivity : BaseActivity() {
    /**
     * The list of all selected and unselected cities, indexed and possibly filtered.
     */
    private lateinit var mCitiesList: ListView

    /**
     * The adapter that presents all of the selected and unselected cities.
     */
    private lateinit var mCitiesAdapter: CityAdapter

    /**
     * Manages all action bar menu display and click handling.
     */
    private val mOptionsMenuManager = OptionsMenuManager()

    /**
     * Menu item controller for search view.
     */
    private lateinit var mSearchMenuItemController: SearchMenuItemController

    /**
     * The controller that shows the drop shadow when content is not scrolled to the top.
     */
    private lateinit var mDropShadowController: DropShadowController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.cities_activity)
        mSearchMenuItemController = SearchMenuItemController(
                getSupportActionBar()!!.getThemedContext(),
                object : SearchView.OnQueryTextListener {
                    override fun onQueryTextSubmit(query: String?): Boolean {
                        return false
                    }

                    override fun onQueryTextChange(query: String): Boolean {
                        mCitiesAdapter.filter(query)
                        updateFastScrolling()
                        return true
                    }
                }, savedInstanceState)
        mCitiesAdapter = CityAdapter(this, mSearchMenuItemController)
        mOptionsMenuManager.addMenuItemController(NavUpMenuItemController(this))
                .addMenuItemController(mSearchMenuItemController)
                .addMenuItemController(SortOrderMenuItemController())
                .addMenuItemController(SettingsMenuItemController(this))
                .addMenuItemController(*MenuItemControllerFactory.getInstance()
                        .buildMenuItemControllers(this))
        mCitiesList = findViewById(R.id.cities_list) as ListView
        mCitiesList.adapter = mCitiesAdapter

        updateFastScrolling()
    }

    override fun onSaveInstanceState(bundle: Bundle) {
        super.onSaveInstanceState(bundle)
        mSearchMenuItemController.saveInstance(bundle)
    }

    override fun onResume() {
        super.onResume()

        // Recompute the contents of the adapter before displaying on screen.
        mCitiesAdapter.refresh()

        val dropShadow: View = findViewById(R.id.drop_shadow)
        mDropShadowController = DropShadowController(dropShadow, mCitiesList)
    }

    override fun onPause() {
        super.onPause()

        mDropShadowController.stop()

        // Save the selected cities.
        DataModel.dataModel.selectedCities = mCitiesAdapter.selectedCities
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        mOptionsMenuManager.onCreateOptionsMenu(menu)
        return true
    }

    override fun onPrepareOptionsMenu(menu: Menu): Boolean {
        mOptionsMenuManager.onPrepareOptionsMenu(menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return (mOptionsMenuManager.onOptionsItemSelected(item) ||
                super.onOptionsItemSelected(item))
    }

    /**
     * Fast scrolling is only enabled while no filtering is happening.
     */
    private fun updateFastScrolling() {
        val enabled: Boolean = !mCitiesAdapter.isFiltering
        mCitiesList.isFastScrollAlwaysVisible = enabled
        mCitiesList.isFastScrollEnabled = enabled
    }

    /**
     * This adapter presents data in 2 possible modes. If selected cities exist the format is:
     *
     * <pre>
     * Selected Cities
     * City 1 (alphabetically first)
     * City 2 (alphabetically second)
     * ...
     * A City A1 (alphabetically first starting with A)
     * City A2 (alphabetically second starting with A)
     * ...
     * B City B1 (alphabetically first starting with B)
     * City B2 (alphabetically second starting with B)
     * ...
     * </pre>
     *
     * If selected cities do not exist, that section is removed and all that remains is:
     *
     * <pre>
     * A City A1 (alphabetically first starting with A)
     * City A2 (alphabetically second starting with A)
     * ...
     * B City B1 (alphabetically first starting with B)
     * City B2 (alphabetically second starting with B)
     * ...
     * </pre>
     */
    private class CityAdapter(
        private val mContext: Context,
        /** Menu item controller for search. Search query is maintained here. */
        private val mSearchMenuItemController: SearchMenuItemController
    ) : BaseAdapter(), View.OnClickListener,
            CompoundButton.OnCheckedChangeListener, SectionIndexer {
        private val mInflater: LayoutInflater = LayoutInflater.from(mContext)

        /**
         * The 12-hour time pattern for the current locale.
         */
        private val mPattern12: String

        /**
         * The 24-hour time pattern for the current locale.
         */
        private val mPattern24: String

        /**
         * `true` time should honor [.mPattern24]; [.mPattern12] otherwise.
         */
        private var mIs24HoursMode = false

        /**
         * A calendar used to format time in a particular timezone.
         */
        private val mCalendar: Calendar = Calendar.getInstance()

        /**
         * The list of cities which may be filtered by a search term.
         */
        private var mFilteredCities: List<City> = emptyList()

        /**
         * A mutable set of cities currently selected by the user.
         */
        private val mUserSelectedCities: MutableSet<City> = ArraySet()

        /**
         * The number of user selections at the top of the adapter to avoid indexing.
         */
        private var mOriginalUserSelectionCount = 0

        /**
         * The precomputed section headers.
         */
        private var mSectionHeaders: Array<String>? = null

        /**
         * The corresponding location of each precomputed section header.
         */
        private var mSectionHeaderPositions: Array<Int>? = null

        init {
            mCalendar.timeInMillis = System.currentTimeMillis()

            val locale = Locale.getDefault()
            mPattern24 = DateFormat.getBestDateTimePattern(locale, "Hm")

            var pattern12 = DateFormat.getBestDateTimePattern(locale, "hma")
            if (TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL) {
                // There's an RTL layout bug that causes jank when fast-scrolling through
                // the list in 12-hour mode in an RTL locale. We can work around this by
                // ensuring the strings are the same length by using "hh" instead of "h".
                pattern12 = pattern12.replace("h".toRegex(), "hh")
            }
            mPattern12 = pattern12
        }

        override fun getCount(): Int {
            val headerCount = if (hasHeader()) 1 else 0
            return headerCount + mFilteredCities.size
        }

        override fun getItem(position: Int): City? {
            if (hasHeader()) {
                val itemViewType = getItemViewType(position)
                when (itemViewType) {
                    VIEW_TYPE_SELECTED_CITIES_HEADER -> return null
                    VIEW_TYPE_CITY -> return mFilteredCities[position - 1]
                }
                throw IllegalStateException("unexpected item view type: $itemViewType")
            }

            return mFilteredCities[position]
        }

        override fun getItemId(position: Int): Long {
            return position.toLong()
        }

        override fun getView(position: Int, view: View?, parent: ViewGroup): View {
            var variableView = view
            val itemViewType = getItemViewType(position)
            when (itemViewType) {
                VIEW_TYPE_SELECTED_CITIES_HEADER -> {
                    return variableView
                            ?: mInflater.inflate(R.layout.city_list_header, parent, false)
                }
                VIEW_TYPE_CITY -> {
                    val city = getItem(position)
                            ?: throw IllegalStateException("The desired city does not exist")
                    val timeZone: TimeZone = city.timeZone

                    // Inflate a new view if necessary.
                    if (variableView == null) {
                        variableView = mInflater.inflate(R.layout.city_list_item, parent, false)
                        val index = variableView.findViewById<View>(R.id.index) as TextView
                        val name = variableView.findViewById<View>(R.id.city_name) as TextView
                        val time = variableView.findViewById<View>(R.id.city_time) as TextView
                        val selected = variableView.findViewById<View>(R.id.city_onoff) as CheckBox
                        variableView.tag = CityItemHolder(index, name, time, selected)
                    }

                    // Bind data into the child views.
                    val holder = variableView!!.tag as CityItemHolder
                    holder.selected.tag = city
                    holder.selected.isChecked = mUserSelectedCities.contains(city)
                    holder.selected.contentDescription = city.name
                    holder.selected.setOnCheckedChangeListener(this)
                    holder.name.setText(city.name, TextView.BufferType.SPANNABLE)
                    holder.time.text = getTimeCharSequence(timeZone)

                    val showIndex = getShowIndex(position)
                    holder.index.visibility = if (showIndex) View.VISIBLE else View.INVISIBLE
                    if (showIndex) {
                        when (citySort) {
                            DataModel.CitySort.NAME -> {
                                holder.index.setText(city.indexString)
                                holder.index.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24f)
                            }
                            DataModel.CitySort.UTC_OFFSET -> {
                                holder.index.text = Utils.getGMTHourOffset(timeZone, false)
                                holder.index.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
                            }
                        }
                    }

                    // skip checkbox and other animations
                    variableView.jumpDrawablesToCurrentState()
                    variableView.setOnClickListener(this)
                    return variableView
                }
                else -> throw IllegalStateException("unexpected item view type: $itemViewType")
            }
        }

        override fun getViewTypeCount(): Int {
            return 2
        }

        override fun getItemViewType(position: Int): Int {
            return if (hasHeader() && position == 0) {
                VIEW_TYPE_SELECTED_CITIES_HEADER
            } else {
                VIEW_TYPE_CITY
            }
        }

        override fun onCheckedChanged(b: CompoundButton, checked: Boolean) {
            val city = b.tag as City
            if (checked) {
                mUserSelectedCities.add(city)
                b.announceForAccessibility(mContext.getString(R.string.city_checked,
                        city.name))
            } else {
                mUserSelectedCities.remove(city)
                b.announceForAccessibility(mContext.getString(R.string.city_unchecked,
                        city.name))
            }
        }

        override fun onClick(v: View) {
            val b = v.findViewById<View>(R.id.city_onoff) as CheckBox
            b.isChecked = !b.isChecked
        }

        override fun getSections(): Array<String>? {
            if (mSectionHeaders == null) {
                // Make an educated guess at the expected number of sections.
                val approximateSectionCount = count / 5
                val sections: MutableList<String> = ArrayList(approximateSectionCount)
                val positions: MutableList<Int> = ArrayList(approximateSectionCount)

                // Add a section for the "Selected Cities" header if it exists.
                if (hasHeader()) {
                    sections.add("+")
                    positions.add(0)
                }

                for (position in 0 until count) {
                    // Add a section if this position should show the section index.
                    if (getShowIndex(position)) {
                        val city = getItem(position)
                                ?: throw IllegalStateException("The desired city does not exist")
                        when (citySort) {
                            DataModel.CitySort.NAME -> sections.add(city.indexString.orEmpty())
                            DataModel.CitySort.UTC_OFFSET -> {
                                val timezone: TimeZone = city.timeZone
                                sections.add(Utils.getGMTHourOffset(timezone, Utils.isPreL()))
                            }
                        }
                        positions.add(position)
                    }
                }

                mSectionHeaders = sections.toTypedArray()
                mSectionHeaderPositions = positions.toTypedArray()
            }
            return mSectionHeaders
        }

        override fun getPositionForSection(sectionIndex: Int): Int {
            return if (sections!!.isEmpty()) 0 else mSectionHeaderPositions!![sectionIndex]
        }

        override fun getSectionForPosition(position: Int): Int {
            if (sections!!.isEmpty()) {
                return 0
            }

            for (i in 0 until mSectionHeaderPositions!!.size - 2) {
                if (position < mSectionHeaderPositions!![i]) continue
                if (position >= mSectionHeaderPositions!![i + 1]) continue
                return i
            }

            return mSectionHeaderPositions!!.size - 1
        }

        /**
         * Clear the section headers to force them to be recomputed if they are now stale.
         */
        fun clearSectionHeaders() {
            mSectionHeaders = null
            mSectionHeaderPositions = null
        }

        /**
         * Rebuilds all internal data structures from scratch.
         */
        fun refresh() {
            // Update the 12/24 hour mode.
            mIs24HoursMode = DateFormat.is24HourFormat(mContext)

            // Refresh the user selections.
            val selected = DataModel.dataModel.selectedCities as List<City>
            mUserSelectedCities.clear()
            mUserSelectedCities.addAll(selected)
            mOriginalUserSelectionCount = selected.size

            // Recompute section headers.
            clearSectionHeaders()

            // Recompute filtered cities.
            filter(mSearchMenuItemController.queryText)
        }

        /**
         * Filter the cities using the given `queryText`.
         */
        fun filter(queryText: String) {
            mSearchMenuItemController.queryText = queryText
            val query = City.removeSpecialCharacters(queryText.toUpperCase())

            // Compute the filtered list of cities.
            val filteredCities = if (TextUtils.isEmpty(query)) {
                DataModel.dataModel.allCities
            } else {
                val unselected: List<City> = DataModel.dataModel.unselectedCities
                val queriedCities: MutableList<City> = ArrayList(unselected.size)
                for (city in unselected) {
                    if (city.matches(query)) {
                        queriedCities.add(city)
                    }
                }
                queriedCities
            }

            // Swap in the filtered list of cities and notify of the data change.
            mFilteredCities = filteredCities
            notifyDataSetChanged()
        }

        val isFiltering: Boolean
            get() = !TextUtils.isEmpty(mSearchMenuItemController.queryText.trim({ it <= ' ' }))

        val selectedCities: Collection<City>
            get() = mUserSelectedCities

        private fun hasHeader(): Boolean {
            return !isFiltering && mOriginalUserSelectionCount > 0
        }

        private val citySort: DataModel.CitySort
            get() = DataModel.dataModel.citySort

        private val citySortComparator: Comparator<City>
            get() = DataModel.dataModel.cityIndexComparator

        private fun getTimeCharSequence(timeZone: TimeZone): CharSequence {
            mCalendar.timeZone = timeZone
            return DateFormat.format(if (mIs24HoursMode) mPattern24 else mPattern12, mCalendar)
        }

        private fun getShowIndex(position: Int): Boolean {
            // Indexes are never displayed on filtered cities.
            if (isFiltering) {
                return false
            }

            if (hasHeader()) {
                // None of the original user selections should show their index.
                if (position <= mOriginalUserSelectionCount) {
                    return false
                }

                // The first item after the original user selections must always show its index.
                if (position == mOriginalUserSelectionCount + 1) {
                    return true
                }
            } else {
                // None of the original user selections should show their index.
                if (position < mOriginalUserSelectionCount) {
                    return false
                }

                // The first item after the original user selections must always show its index.
                if (position == mOriginalUserSelectionCount) {
                    return true
                }
            }

            // Otherwise compare the city with its predecessor to test if it is a header.
            val priorCity = getItem(position - 1)
            val city = getItem(position)
            return citySortComparator.compare(priorCity, city) != 0
        }

        /**
         * Cache the child views of each city item view.
         */
        private class CityItemHolder(
            val index: TextView,
            val name: TextView,
            val time: TextView,
            val selected: CheckBox
        )

        companion object {
            /**
             * The type of the single optional "Selected Cities" header entry.
             */
            private const val VIEW_TYPE_SELECTED_CITIES_HEADER = 0

            /**
             * The type of each city entry.
             */
            private const val VIEW_TYPE_CITY = 1
        }
    }

    private inner class SortOrderMenuItemController : MenuItemController {
        private val SORT_MENU_RES_ID = R.id.menu_item_sort

        override val id: Int
            get() = SORT_MENU_RES_ID

        override fun onCreateOptionsItem(menu: Menu) {
            menu.add(Menu.NONE, R.id.menu_item_sort, Menu.NONE,
                    R.string.menu_item_sort_by_gmt_offset)
                    .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
        }

        override fun onPrepareOptionsItem(item: MenuItem) {
            item.setTitle(if (DataModel.dataModel.citySort == DataModel.CitySort.NAME) {
                R.string.menu_item_sort_by_gmt_offset
            } else {
                R.string.menu_item_sort_by_name
            })
        }

        override fun onOptionsItemSelected(item: MenuItem): Boolean {
            // Save the new sort order.
            DataModel.dataModel.toggleCitySort()

            // Section headers are influenced by sort order and must be cleared.
            mCitiesAdapter.clearSectionHeaders()

            // Honor the new sort order in the adapter.
            mCitiesAdapter.filter(mSearchMenuItemController.queryText)
            return true
        }
    }
}