package com.kdanmobile.reader.thumb

import android.app.AlertDialog
import android.app.Dialog
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.support.v7.widget.GridLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.Toolbar
import android.support.v7.widget.helper.ItemTouchHelper
import android.view.*
import com.kdanmobile.reader.R
import com.kdanmobile.reader.ReaderActivity
import com.kdanmobile.reader.ReaderViewModel
import com.kdanmobile.reader.thumb.mode.EditMode
import com.kdanmobile.reader.thumb.mode.NormalMode
import com.kdanmobile.reader.widget.drag.OnRecyclerItemClickListener
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import org.koin.android.viewmodel.ext.android.sharedViewModel
import org.koin.android.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.io.File

abstract class PdfThumbDialogFragment: DialogFragment(), PdfThumbAdapter.PageMoveHandler {
    abstract fun provideIntent(): Intent
    abstract fun canDelete(): Boolean
    abstract fun canExtract() : Boolean
    abstract fun canChangePage() : Boolean
    abstract fun getTrialDays(): Long
    abstract fun getSubscribeRunnable(): Runnable
    abstract fun getHeight(): Int
    abstract fun getWidth(): Int
    abstract fun getPadding(): Int
    abstract fun getColumns(): Int
    abstract fun getCreateExtractBlankFile(pdfFilename: String, selectPage: String): File

    private val readerViewModel: ReaderViewModel by sharedViewModel()
    private val viewModel: PdfThumbViewModel by viewModel { parametersOf(readerViewModel.readerModel) }
    private lateinit var pdfThumbAdapter: PdfThumbAdapter

    private var thumbFragmentListener: PdfThumbFragmentListener? = null
        get() = if (activity is PdfThumbFragmentListener) (activity as PdfThumbFragmentListener) else null

    private lateinit var toolbar_pdfThumb: Toolbar
    private lateinit var recyclerView: RecyclerView

    private var disposable: Disposable? = null
    private var editMode = EditMode()
    private var normalMode = NormalMode()
    private var columns = 0
    private var height = 0
    private var width = 0
    private var padding = 0

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val view = LayoutInflater.from(context).inflate(R.layout.activity_pdf_thumb, null)
        initViews(view)
        loadThumbAsynchronously()
        initToolBar()

        val dialog = object: Dialog(activity!!) {
            override fun onBackPressed() {
                onClickToolBarNavigation()
            }
        }
        dialog.window?.requestFeature(Window.FEATURE_NO_TITLE)
        dialog.setContentView(view)
        dialog.window?.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT)
        dialog.window?.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)

        if (thumbFragmentListener?.isShowStateBar() == true) {
            dialog.window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
        }
        dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))

        return dialog
    }

    override fun onPause() {
        viewModel.temporarySave()
        super.onPause()
    }

    private fun initViews(view: View) {
        toolbar_pdfThumb = view.findViewById(R.id.toolbar_pdfThumb)
        recyclerView = view.findViewById(R.id.id_recyclerview)
        recyclerView.setHasFixedSize(true)
        setViewSize()
    }

    private fun setViewSize() {
        val context = activity!!
        if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            if (ScreenUtil.getXDp(activity!!) >= 720) {
                columns = 6
                width = (ScreenUtil.getScreenWidth(context) / 6.6).toInt()
            } else {
                columns = 5
                width = (ScreenUtil.getScreenWidth(context) / 5.5).toInt()
            }
        } else {
            if (ScreenUtil.getXDp(activity!!) >= 720) {
                columns = 4
                width = (ScreenUtil.getScreenWidth(context) / 4.4).toInt()
            } else {
                columns = 3
                width = (ScreenUtil.getScreenWidth(context) / 3.3).toInt()
            }
        }
        padding = (ScreenUtil.getScreenWidth(context) - width * columns) / 2 * (columns + 1)
        height = 234 * width / 180
    }

    private fun loadThumbAsynchronously() {
        disposable = viewModel.initThumbData(height, width, padding)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    pdfThumbAdapter = PdfThumbAdapter(it,this, viewModel.thumbnailHandler)
                    recyclerView.adapter = pdfThumbAdapter
                    recyclerView.layoutManager = GridLayoutManager(activity!!, columns)
                    recyclerView.addOnItemTouchListener(object : OnRecyclerItemClickListener(recyclerView) {
                        override fun onItemClick(vh: RecyclerView.ViewHolder) {
                            viewModel.mode.onPageItemClick(this@PdfThumbDialogFragment, vh.adapterPosition, viewModel.mapSelect, pdfThumbAdapter)
                        }
                        override fun onItemLongClick(vh: RecyclerView.ViewHolder) {}
                    })
                    recyclerView.scrollToPosition(viewModel.pdfInfoHandler.getCurrentPage())
                    val itemTouchHelperCallBack = ItemTouchHelpCallback(pdfThumbAdapter)
                    val itemTouchHelper = ItemTouchHelper(itemTouchHelperCallBack)
                    itemTouchHelper.attachToRecyclerView(recyclerView)
                }, {
                    it.printStackTrace()
                })
    }

    override fun onDestroy() {
        disposable?.dispose()
        super.onDestroy()
    }

    private fun initToolBar() {
        toolbar_pdfThumb.inflateMenu(R.menu.menu_thumb)
        toolbar_pdfThumb.setOnMenuItemClickListener {item: MenuItem ->
            when (item.itemId) {
                R.id.item_action_edit_thumb -> switchToEditMode()
                R.id.item_action_select_all_thumb -> onClickSelectAllBtn()
                R.id.item_action_rorate_thumb -> onClickRotateBtn()
                R.id.item_action_delete_thumb -> onClickDeleteBtn()
                R.id.item_action_extract_thumb -> onClickExtractBtn()
            }
            return@setOnMenuItemClickListener true
        }

        toolbar_pdfThumb.setNavigationOnClickListener {
            onClickToolBarNavigation()
        }
        updateToolbar()
    }

    private fun invalidateOptionsMenu() {
        if (!viewModel.passwordHandler.isNeedPassword()) {
            val menu = toolbar_pdfThumb.menu
            when (viewModel.isEdit) {
                true -> {
                    val isExtractEnable = viewModel.hasSelectItem()
                    val isRotateEnable = viewModel.hasSelectItem()
                    val isDeleteEnable = viewModel.hasSelectItem() && !viewModel.isAllItemSelect()
                    val visible = viewModel.isPdf
                    menu.findItem(R.id.item_action_edit_thumb).isVisible = false
                    menu.findItem(R.id.item_action_select_all_thumb)
                            .setVisible(visible)
                            .setIcon(if (viewModel.isAllItemSelect()) R.drawable.selector_deselect_all_btn_action_bar else R.drawable.selector_select_all_btn_action_bar)
                    menu.findItem(R.id.item_action_extract_thumb)
                            .setVisible(visible).isEnabled = isExtractEnable
                    menu.findItem(R.id.item_action_rorate_thumb)
                            .setVisible(visible).isEnabled = isRotateEnable
                    menu.findItem(R.id.item_action_delete_thumb)
                            .setVisible(visible).isEnabled = isDeleteEnable
                }
                false -> {
                    val visible = viewModel.isPdf
                    menu.findItem(R.id.item_action_edit_thumb).isVisible = visible
                    menu.findItem(R.id.item_action_select_all_thumb).isVisible = false
                    menu.findItem(R.id.item_action_extract_thumb).isVisible = false
                    menu.findItem(R.id.item_action_rorate_thumb).isVisible = false
                    menu.findItem(R.id.item_action_delete_thumb).isVisible = false
                }
            }
        } else {
            val menu = toolbar_pdfThumb.menu
            menu.findItem(R.id.item_action_edit_thumb).isVisible = false
            menu.findItem(R.id.item_action_select_all_thumb).isVisible = false
            menu.findItem(R.id.item_action_extract_thumb).isVisible = false
            menu.findItem(R.id.item_action_rorate_thumb).isVisible = false
            menu.findItem(R.id.item_action_delete_thumb).isVisible = false
        }
    }

    override fun onStop() {
        viewModel.updateBookmarkDisplay()
        viewModel.temporarySave()
        super.onStop()
    }

    private fun onClickToolBarNavigation(){
        when (viewModel.isEdit) {
            true -> {
                switchToNormalMode()
                invalidateOptionsMenu()
                onModeSwitched()
            }
            false -> {
                viewModel.pdfInfoHandler.goToCurrentPage(viewModel.pdfInfoHandler.getCurrentPage())
                dismiss()
            }
        }
    }

    private fun switchToEditMode() {
        viewModel.mode = editMode
        viewModel.isEdit = true
        viewModel.thumbData.isEditMode = true
        pdfThumbAdapter.setThumbData(viewModel.thumbData)
        onModeSwitched()
    }

    private fun switchToNormalMode() {
        viewModel.mode = normalMode
        viewModel.isEdit = false
        viewModel.thumbData.isEditMode = false
        pdfThumbAdapter.setThumbData(viewModel.thumbData)
        viewModel.setAllUnSelect()
        onModeSwitched()
    }

    private fun onModeSwitched() {
        updateToolbar()
    }

    fun updateToolbar() {
        invalidateOptionsMenu()
        when (viewModel.isEdit) {
            true -> {
                toolbar_pdfThumb.setTitle(R.string.pdf_thumb_title_edit_mode)
                toolbar_pdfThumb.setNavigationIcon(R.drawable.selector_close_btn_navigation)
            }
            false -> {
                toolbar_pdfThumb.setTitle(R.string.thumbnail)
                toolbar_pdfThumb.setNavigationIcon(R.drawable.selector_arrowback)
            }
        }
    }

    private fun onClickSelectAllBtn() {
        if (!viewModel.isAllItemSelect()) {
            viewModel.setAllSelect()
        } else {
            viewModel.setAllUnSelect()
        }
        pdfThumbAdapter.notifyItemRangeChanged(0, pdfThumbAdapter.itemCount)
        updateToolbar()
    }

    private fun onClickRotateBtn() {
        val runnable = Runnable {
            for (key in viewModel.mapSelect.keys) {
                if (viewModel.mapSelect[key] == true) {
                    pdfThumbAdapter.notifyItemChanged(key)
                }
            }
        }
        viewModel.pageRotate(runnable)
    }

    private fun onClickExtractBtn() {
        if (!canExtract()) {
            getSubscribeRunnable().run()
        } else {
            val pagesForFile = FileUtil.generateSelectedPagesString(viewModel.getSelectPage())
            val dst = FileUtil.createExtractBlankFile(viewModel.pdfInfoHandler.getOpenPdfFilename(), pagesForFile, FileUtil.getKdanPDFReaderFolder())
            val runnable = Runnable {
                val filePath = String.format("/%s/%s", dst.parentFile.name, dst.name)
                val msg = getString(R.string.pdf_thumb_extract_page_suc_dialog_msg, filePath)
                AlertDialog.Builder(activity)
                        .setTitle(R.string.pdf_thumb_extract_page_suc_dialog_title)
                        .setMessage(msg)
                        .setPositiveButton(R.string.pdf_thumb_extract_page_suc_dialog_positive_btn) { _, _ ->
                            val intent = provideIntent()
                            intent.putExtra(ReaderActivity.KEY_FILE_ABSOLUTE, dst.absolutePath)
                            intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
                            startActivity(intent)
                        }
                        .show()
            }
            val runnableForFail = Runnable {
                AlertDialog.Builder(activity)
                        .setTitle(R.string.pdf_thumb_extract_page_failed_dialog_title)
                        .setMessage(R.string.pdf_thumb_extract_page_failed_dialog_msg)
                        .show()
            }
            viewModel.pageExtract(dst, runnable, runnableForFail)
        }
    }

    private fun onClickDeleteBtn() {
        if (!canDelete()) {
            getSubscribeRunnable().run()
        } else {
            val builder = AlertDialog.Builder(activity)
            builder.setMessage(R.string.pdf_thumb_delete_check_dialog_msg)
            builder.setNegativeButton(android.R.string.no) { dialog, _ -> dialog.dismiss() }
            builder.setPositiveButton(android.R.string.yes) { _, _ ->
                viewModel.pageDelete(Runnable {
                    viewModel.setAllUnSelect()
                    updateToolbar()
                    pdfThumbAdapter.notifyDataSetChanged() }) }
            builder.create().show()
        }
    }

    override fun onPageMove(fromPage: Int, toPage: Int) {
        if (!canChangePage()) {
            getSubscribeRunnable().run()
        } else {
            viewModel.reorderPage(fromPage, toPage)
        }
    }

    fun moveToPage(pageIndex: Int) {
        viewModel.pdfInfoHandler.goToCurrentPage(pageIndex)
    }
}