package org.mariotaku.twidere.fragment

import android.accounts.Account
import android.accounts.AccountManager
import android.app.Activity
import android.app.Dialog
import android.content.ContentResolver
import android.content.ContentValues
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import androidx.loader.app.LoaderManager
import androidx.loader.content.Loader
import androidx.appcompat.app.AlertDialog
import android.view.*
import android.view.ContextMenu.ContextMenuInfo
import android.widget.AdapterView
import android.widget.AdapterView.AdapterContextMenuInfo
import kotlinx.android.synthetic.main.layout_draggable_list_with_empty_view.*
import nl.komponents.kovenant.task
import org.mariotaku.kpreferences.get
import org.mariotaku.ktextension.Bundle
import org.mariotaku.ktextension.set
import org.mariotaku.sqliteqb.library.Expression
import org.mariotaku.twidere.Constants.*
import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.ACCOUNT_AUTH_TOKEN_TYPE
import org.mariotaku.twidere.TwidereConstants.ACCOUNT_TYPE
import org.mariotaku.twidere.activity.ColorPickerDialogActivity
import org.mariotaku.twidere.adapter.AccountDetailsAdapter
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY
import org.mariotaku.twidere.constant.newDocumentApiKey
import org.mariotaku.twidere.extension.applyTheme
import org.mariotaku.twidere.extension.model.getAccountKey
import org.mariotaku.twidere.extension.model.setActivated
import org.mariotaku.twidere.extension.model.setColor
import org.mariotaku.twidere.extension.model.setPosition
import org.mariotaku.twidere.extension.onShow
import org.mariotaku.twidere.loader.AccountDetailsLoader
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.AccountPreferences
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses
import org.mariotaku.twidere.util.DataStoreUtils
import org.mariotaku.twidere.util.IntentUtils
import org.mariotaku.twidere.util.deleteAccountData
import org.mariotaku.twidere.util.support.removeAccountSupport

/**
 * Sort and toggle account availability
 * Created by mariotaku on 14/10/26.
 */
class AccountsManagerFragment : BaseFragment(), LoaderManager.LoaderCallbacks<List<AccountDetails>>,
        AdapterView.OnItemClickListener {

    private lateinit var adapter: AccountDetailsAdapter

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        setHasOptionsMenu(true)
        val am = AccountManager.get(context)
        adapter = AccountDetailsAdapter(context!!, requestManager).apply {
            sortEnabled = true
            switchEnabled = true
            accountToggleListener = { pos, checked ->
                val item = getItem(pos)
                item.activated = checked
                item.account.setActivated(am, checked)
            }
        }
        listView.adapter = adapter
        listView.isDragEnabled = true
        listView.onItemClickListener = this
        listView.setDropListener { from, to ->
            adapter.drop(from, to)
            for (i in 0 until adapter.count) {
                val item = adapter.getItem(i)
                item.account.setActivated(am, item.activated)
                item.account.setPosition(am, i)
            }
        }
        listView.setOnCreateContextMenuListener(this)
        listView.emptyView = emptyView
        emptyText.setText(R.string.message_toast_no_account)
        emptyIcon.setImageResource(R.drawable.ic_info_error_generic)
        setListShown(false)

        loaderManager.initLoader(0, null, this)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        when (requestCode) {
            REQUEST_SET_COLOR -> {
                if (resultCode != Activity.RESULT_OK || data == null)
                    return
                val am = AccountManager.get(context)
                val accountKey: UserKey = data.getBundleExtra(EXTRA_EXTRAS).getParcelable(EXTRA_ACCOUNT_KEY) ?: return
                val color = data.getIntExtra(EXTRA_COLOR, Color.WHITE)
                val details = adapter.findItem(accountKey) ?: return
                details.color = color
                details.account.setColor(am, color)
                val resolver = context?.contentResolver
                task {
                    resolver?.let { updateContentsColor(it, details) }
                }
                adapter.notifyDataSetChanged()
                return
            }
        }
        super.onActivityResult(requestCode, resultCode, data)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.add_account -> {
                AccountManager.get(context).addAccount(ACCOUNT_TYPE, ACCOUNT_AUTH_TOKEN_TYPE,
                        null, null, activity, null, null)
            }
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.menu_accounts_manager, menu)
    }

    override fun onContextItemSelected(item: MenuItem): Boolean {
        val menuInfo = item.menuInfo as? AdapterContextMenuInfo ?: return false
        val details = adapter.getItem(menuInfo.position) ?: return false
        when (item.itemId) {
            R.id.set_color -> {
                val intent = Intent(activity, ColorPickerDialogActivity::class.java)
                intent.putExtra(EXTRA_COLOR, details.color)
                intent.putExtra(EXTRA_EXTRAS, Bundle {
                    this[EXTRA_ACCOUNT_KEY] = details.key
                })
                intent.putExtra(EXTRA_ALPHA_SLIDER, false)
                startActivityForResult(intent, REQUEST_SET_COLOR)
            }
            R.id.delete -> {
                val f = AccountDeletionDialogFragment()
                val args = Bundle()
                args.putParcelable(EXTRA_ACCOUNT, details.account)
                f.arguments = args
                f.show(childFragmentManager, FRAGMENT_TAG_ACCOUNT_DELETION)
            }
        }
        return false
    }

    override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
        val account = adapter.getItem(position)
        context?.let {
            IntentUtils.openUserProfile(it, account.user, preferences[newDocumentApiKey],
                null)
        }
    }

    override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<AccountDetails>> {
        return AccountDetailsLoader(context!!)
    }

    override fun onLoaderReset(loader: Loader<List<AccountDetails>>) {

    }

    override fun onLoadFinished(loader: Loader<List<AccountDetails>>, data: List<AccountDetails>) {
        adapter.apply {
            clear()
            addAll(data)
        }
        setListShown(true)
    }

    override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenuInfo?) {
        if (menuInfo !is AdapterContextMenuInfo) return
        val account = adapter.getItem(menuInfo.position)!!
        menu.setHeaderTitle(account.user.name)
        val inflater = MenuInflater(v.context)
        inflater.inflate(R.menu.action_manager_account, menu)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.layout_draggable_list_with_empty_view, container, false)
    }

    private fun setListShown(shown: Boolean) {
        listContainer.visibility = if (shown) View.VISIBLE else View.GONE
        progressContainer.visibility = if (shown) View.GONE else View.VISIBLE
    }

    private fun updateContentsColor(resolver: ContentResolver, details: AccountDetails) {
        val statusValues = ContentValues().apply {
            put(Statuses.ACCOUNT_COLOR, details.color)
        }
        val statusesWhere = Expression.equalsArgs(Statuses.ACCOUNT_KEY)
        val statusesWhereArgs = arrayOf(details.key.toString())

        DataStoreUtils.STATUSES_ACTIVITIES_URIS.forEach { uri ->
            resolver.update(uri, statusValues, statusesWhere.sql, statusesWhereArgs)
        }
    }

    /**
     * DELETE YOUR ACCOUNT
     */
    class AccountDeletionDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener {

        override fun onClick(dialog: DialogInterface, which: Int) {
            val account: Account = arguments?.getParcelable(EXTRA_ACCOUNT)!!
            val resolver = context?.contentResolver
            val am = AccountManager.get(context)
            when (which) {
                DialogInterface.BUTTON_POSITIVE -> {
                    val accountKey = account.getAccountKey(am)
                    resolver?.deleteAccountData(accountKey)
                    context?.let {
                        AccountPreferences.getSharedPreferencesForAccount(it, accountKey).edit()
                                .clear().apply()
                    }
                    am.removeAccountSupport(account)
                }
            }
        }


        override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
            val context = context
            val builder = AlertDialog.Builder(context!!)
            builder.setNegativeButton(android.R.string.cancel, null)
            builder.setPositiveButton(android.R.string.ok, this)
            builder.setTitle(R.string.title_account_delete_confirm)
            builder.setMessage(R.string.message_account_delete_confirm)
            val dialog = builder.create()
            dialog.onShow { it.applyTheme() }
            return dialog
        }

    }

    companion object {

        private val FRAGMENT_TAG_ACCOUNT_DELETION = "account_deletion"
    }
}
