/*
 * 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.app.FragmentManager
import android.app.backup.BackupManager
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.media.Ringtone
import android.media.RingtoneManager
import android.net.Uri
import android.os.Bundle
import android.os.Vibrator
import android.preference.CheckBoxPreference
import android.preference.ListPreference
import android.preference.Preference
import android.preference.Preference.OnPreferenceChangeListener
import android.preference.Preference.OnPreferenceClickListener
import android.preference.PreferenceCategory
import android.preference.PreferenceFragment
import android.preference.PreferenceManager
import android.preference.PreferenceScreen
import android.provider.CalendarContract
import android.provider.CalendarContract.CalendarCache
import android.text.TextUtils
import android.text.format.Time
import com.android.calendar.alerts.AlertReceiver
import com.android.timezonepicker.TimeZoneInfo
import com.android.timezonepicker.TimeZonePickerDialog
import com.android.timezonepicker.TimeZonePickerDialog.OnTimeZoneSetListener
import com.android.timezonepicker.TimeZonePickerUtils

class GeneralPreferences : PreferenceFragment(), OnSharedPreferenceChangeListener,
        OnPreferenceChangeListener, OnTimeZoneSetListener {
    var mAlert: CheckBoxPreference? = null
    var mVibrate: CheckBoxPreference? = null
    var mPopup: CheckBoxPreference? = null
    var mUseHomeTZ: CheckBoxPreference? = null
    var mHideDeclined: CheckBoxPreference? = null
    var mHomeTZ: Preference? = null
    var mTzPickerUtils: TimeZonePickerUtils? = null
    var mWeekStart: ListPreference? = null
    var mDefaultReminder: ListPreference? = null
    private var mTimeZoneId: String? = null

    @Override
    override fun onCreate(icicle: Bundle?) {
        super.onCreate(icicle)
        val activity: Activity = getActivity()

        // Make sure to always use the same preferences file regardless of the package name
        // we're running under
        val preferenceManager: PreferenceManager = getPreferenceManager()
        val sharedPreferences: SharedPreferences? = getSharedPreferences(activity)
        preferenceManager.setSharedPreferencesName(SHARED_PREFS_NAME)

        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.general_preferences)
        val preferenceScreen: PreferenceScreen = getPreferenceScreen()
        mAlert = preferenceScreen.findPreference(KEY_ALERTS) as CheckBoxPreference
        mVibrate = preferenceScreen.findPreference(KEY_ALERTS_VIBRATE) as CheckBoxPreference
        val vibrator: Vibrator = activity.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
        if (vibrator == null || !vibrator.hasVibrator()) {
            val mAlertGroup: PreferenceCategory = preferenceScreen
                    .findPreference(KEY_ALERTS_CATEGORY) as PreferenceCategory
            mAlertGroup.removePreference(mVibrate)
        }
        mPopup = preferenceScreen.findPreference(KEY_ALERTS_POPUP) as CheckBoxPreference
        mUseHomeTZ = preferenceScreen.findPreference(KEY_HOME_TZ_ENABLED) as CheckBoxPreference
        mHideDeclined = preferenceScreen.findPreference(KEY_HIDE_DECLINED) as CheckBoxPreference
        mWeekStart = preferenceScreen.findPreference(KEY_WEEK_START_DAY) as ListPreference
        mDefaultReminder = preferenceScreen.findPreference(KEY_DEFAULT_REMINDER) as ListPreference
        mHomeTZ = preferenceScreen.findPreference(KEY_HOME_TZ)
        mWeekStart?.setSummary(mWeekStart?.getEntry())
        mDefaultReminder?.setSummary(mDefaultReminder?.getEntry())

        // This triggers an asynchronous call to the provider to refresh the data in shared pref
        mTimeZoneId = Utils.getTimeZone(activity, null)
        val prefs: SharedPreferences = CalendarUtils.getSharedPreferences(activity,
                Utils.SHARED_PREFS_NAME)

        // Utils.getTimeZone will return the currentTimeZone instead of the one
        // in the shared_pref if home time zone is disabled. So if home tz is
        // off, we will explicitly read it.
        if (!prefs.getBoolean(KEY_HOME_TZ_ENABLED, false)) {
            mTimeZoneId = prefs.getString(KEY_HOME_TZ, Time.getCurrentTimezone())
        }

        mHomeTZ?.setOnPreferenceClickListener(object : Preference.OnPreferenceClickListener {
            @Override
            override fun onPreferenceClick(preference: Preference?): Boolean {
                showTimezoneDialog()
                return true
            }
        })

        if (mTzPickerUtils == null) {
            mTzPickerUtils = TimeZonePickerUtils(getActivity())
        }
        val timezoneName: CharSequence? = mTzPickerUtils?.getGmtDisplayName(getActivity(),
                mTimeZoneId, System.currentTimeMillis(), false)
        mHomeTZ?.setSummary(timezoneName ?: mTimeZoneId)
        val tzpd: TimeZonePickerDialog = activity.getFragmentManager()
                .findFragmentByTag(FRAG_TAG_TIME_ZONE_PICKER) as TimeZonePickerDialog
        if (tzpd != null) {
            tzpd.setOnTimeZoneSetListener(this)
        }
        migrateOldPreferences(sharedPreferences)
        updateChildPreferences()
    }

    private fun showTimezoneDialog() {
        val activity: Activity = getActivity() ?: return
        val b = Bundle()
        b.putLong(TimeZonePickerDialog.BUNDLE_START_TIME_MILLIS, System.currentTimeMillis())
        b.putString(TimeZonePickerDialog.BUNDLE_TIME_ZONE, Utils.getTimeZone(activity, null))
        val fm: FragmentManager = getActivity().getFragmentManager()
        var tzpd: TimeZonePickerDialog? = fm
                .findFragmentByTag(FRAG_TAG_TIME_ZONE_PICKER) as TimeZonePickerDialog
        if (tzpd != null) {
            tzpd.dismiss()
        }
        tzpd = TimeZonePickerDialog()
        tzpd.setArguments(b)
        tzpd.setOnTimeZoneSetListener(this)
        tzpd.show(fm, FRAG_TAG_TIME_ZONE_PICKER)
    }

    @Override
    override fun onStart() {
        super.onStart()
        getPreferenceScreen().getSharedPreferences()
                .registerOnSharedPreferenceChangeListener(this)
        setPreferenceListeners(this)
    }

    /**
     * Sets up all the preference change listeners to use the specified
     * listener.
     */
    private fun setPreferenceListeners(listener: OnPreferenceChangeListener?) {
        mUseHomeTZ?.setOnPreferenceChangeListener(listener)
        mHomeTZ?.setOnPreferenceChangeListener(listener)
        mWeekStart?.setOnPreferenceChangeListener(listener)
        mDefaultReminder?.setOnPreferenceChangeListener(listener)
        mHideDeclined?.setOnPreferenceChangeListener(listener)
        mVibrate?.setOnPreferenceChangeListener(listener)
    }

    @Override
    override fun onStop() {
        getPreferenceScreen().getSharedPreferences()
                .unregisterOnSharedPreferenceChangeListener(this)
        setPreferenceListeners(null)
        super.onStop()
    }

    @Override
    override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String) {
        val a: Activity = getActivity()
        if (key.equals(KEY_ALERTS)) {
            updateChildPreferences()
            if (a != null) {
                val intent = Intent()
                intent.setClass(a, AlertReceiver::class.java)
                if (mAlert?.isChecked() ?: false) {
                    intent.setAction(AlertReceiver.ACTION_DISMISS_OLD_REMINDERS)
                } else {
                    intent.setAction(AlertReceiver.EVENT_REMINDER_APP_ACTION)
                }
                a.sendBroadcast(intent)
            }
        }
        if (a != null) {
            BackupManager.dataChanged(a.getPackageName())
        }
    }

    /**
     * Handles time zone preference changes
     */
    @Override
    override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
        val tz: String?
        val activity: Activity = getActivity()
        if (preference === mUseHomeTZ) {
            tz = if (newValue != null) {
                mTimeZoneId
            } else {
                CalendarCache.TIMEZONE_TYPE_AUTO
            }
            Utils.setTimeZone(activity, tz)
            return true
        } else if (preference === mHideDeclined) {
            mHideDeclined?.setChecked(newValue as Boolean)
            val intent = Intent(Utils.getWidgetScheduledUpdateAction(activity))
            intent.setDataAndType(CalendarContract.CONTENT_URI, Utils.APPWIDGET_DATA_TYPE)
            activity.sendBroadcast(intent)
            return true
        } else if (preference === mWeekStart) {
            mWeekStart?.setValue(newValue as String)
            mWeekStart?.setSummary(mWeekStart?.getEntry())
        } else if (preference === mDefaultReminder) {
            mDefaultReminder?.setValue(newValue as String)
            mDefaultReminder?.setSummary(mDefaultReminder?.getEntry())
        } else if (preference === mVibrate) {
            mVibrate?.setChecked(newValue as Boolean)
            return true
        } else {
            return true
        }
        return false
    }

    fun getRingtoneTitleFromUri(context: Context?, uri: String?): String? {
        if (TextUtils.isEmpty(uri)) {
            return null
        }
        val ring: Ringtone = RingtoneManager.getRingtone(getActivity(), Uri.parse(uri))
        return if (ring != null) {
            ring.getTitle(context)
        } else null
    }

    /**
     * If necessary, upgrades previous versions of preferences to the current
     * set of keys and values.
     * @param prefs the preferences to upgrade
     */
    private fun migrateOldPreferences(prefs: SharedPreferences?) {
        // If needed, migrate vibration setting from a previous version
        mVibrate?.setChecked(Utils.getDefaultVibrate(getActivity(), prefs))

        // If needed, migrate the old alerts type settin
        if (prefs?.contains(KEY_ALERTS) == false && prefs?.contains(KEY_ALERTS_TYPE) == true) {
            val type: String? = prefs?.getString(KEY_ALERTS_TYPE, ALERT_TYPE_STATUS_BAR)
            if (type.equals(ALERT_TYPE_OFF)) {
                mAlert?.setChecked(false)
                mPopup?.setChecked(false)
                mPopup?.setEnabled(false)
            } else if (type.equals(ALERT_TYPE_STATUS_BAR)) {
                mAlert?.setChecked(true)
                mPopup?.setChecked(false)
                mPopup?.setEnabled(true)
            } else if (type.equals(ALERT_TYPE_ALERTS)) {
                mAlert?.setChecked(true)
                mPopup?.setChecked(true)
                mPopup?.setEnabled(true)
            }
            // clear out the old setting
            prefs?.edit().remove(KEY_ALERTS_TYPE).commit()
        }
    }

    /**
     * Keeps the dependent settings in sync with the parent preference, so for
     * example, when notifications are turned off, we disable the preferences
     * for configuring the exact notification behavior.
     */
    private fun updateChildPreferences() {
        if (mAlert?.isChecked() ?: false) {
            mVibrate?.setEnabled(true)
            mPopup?.setEnabled(true)
        } else {
            mVibrate?.setEnabled(false)
            mPopup?.setEnabled(false)
        }
    }

    @Override
    override fun onPreferenceTreeClick(
        preferenceScreen: PreferenceScreen?,
        preference: Preference
    ): Boolean {
        val key: String = preference.getKey()
        return super.onPreferenceTreeClick(preferenceScreen, preference)
    }

    @Override
    override fun onTimeZoneSet(tzi: TimeZoneInfo) {
        if (mTzPickerUtils == null) {
            mTzPickerUtils = TimeZonePickerUtils(getActivity())
        }
        val timezoneName: CharSequence? = mTzPickerUtils?.getGmtDisplayName(
                getActivity(), tzi.mTzId, System.currentTimeMillis(), false)
        mHomeTZ?.setSummary(timezoneName)
        Utils.setTimeZone(getActivity(), tzi.mTzId)
    }

    companion object {
        // 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 SHARED_PREFS_NAME_NO_BACKUP = "com.android.calendar_preferences_no_backup"
        private const val FRAG_TAG_TIME_ZONE_PICKER = "TimeZonePicker"

        // Preference keys
        const val KEY_HIDE_DECLINED = "preferences_hide_declined"
        const val KEY_WEEK_START_DAY = "preferences_week_start_day"
        const val KEY_SHOW_WEEK_NUM = "preferences_show_week_num"
        const val KEY_DAYS_PER_WEEK = "preferences_days_per_week"
        const val KEY_SKIP_SETUP = "preferences_skip_setup"
        const val KEY_CLEAR_SEARCH_HISTORY = "preferences_clear_search_history"
        const val KEY_ALERTS_CATEGORY = "preferences_alerts_category"
        const val KEY_ALERTS = "preferences_alerts"
        const val KEY_ALERTS_VIBRATE = "preferences_alerts_vibrate"
        const val KEY_ALERTS_RINGTONE = "preferences_alerts_ringtone"
        const val KEY_ALERTS_POPUP = "preferences_alerts_popup"
        const val KEY_SHOW_CONTROLS = "preferences_show_controls"
        const val KEY_DEFAULT_REMINDER = "preferences_default_reminder"
        const val NO_REMINDER = -1
        const val NO_REMINDER_STRING = "-1"
        const val REMINDER_DEFAULT_TIME = 10 // in minutes
        const val KEY_DEFAULT_CELL_HEIGHT = "preferences_default_cell_height"
        const val KEY_VERSION = "preferences_version"

        /** Key to SharePreference for default view (CalendarController.ViewType)  */
        const val KEY_START_VIEW = "preferred_startView"

        /**
         * Key to SharePreference for default detail view (CalendarController.ViewType)
         * Typically used by widget
         */
        const val KEY_DETAILED_VIEW = "preferred_detailedView"
        const val KEY_DEFAULT_CALENDAR = "preference_defaultCalendar"

        // These must be in sync with the array preferences_week_start_day_values
        const val WEEK_START_DEFAULT = "-1"
        const val WEEK_START_SATURDAY = "7"
        const val WEEK_START_SUNDAY = "1"
        const val WEEK_START_MONDAY = "2"

        // These keys are kept to enable migrating users from previous versions
        private const val KEY_ALERTS_TYPE = "preferences_alerts_type"
        private const val ALERT_TYPE_ALERTS = "0"
        private const val ALERT_TYPE_STATUS_BAR = "1"
        private const val ALERT_TYPE_OFF = "2"
        const val KEY_HOME_TZ_ENABLED = "preferences_home_tz_enabled"
        const val KEY_HOME_TZ = "preferences_home_tz"

        // Default preference values
        const val DEFAULT_START_VIEW: Int = CalendarController.ViewType.WEEK
        const val DEFAULT_DETAILED_VIEW: Int = CalendarController.ViewType.DAY
        const val DEFAULT_SHOW_WEEK_NUM = false

        // This should match the XML file.
        const val DEFAULT_RINGTONE = "content://settings/system/notification_sound"

        /** Return a properly configured SharedPreferences instance  */
        @JvmStatic
        fun getSharedPreferences(context: Context?): SharedPreferences? {
            return context?.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
        }

        /** Set the default shared preferences in the proper context  */
        @JvmStatic
        fun setDefaultValues(context: Context?) {
            PreferenceManager.setDefaultValues(context, SHARED_PREFS_NAME, Context.MODE_PRIVATE,
                    R.xml.general_preferences, false)
        }
    }
}