package com.kdanmobile.reader.screen.adapter

import android.graphics.Bitmap
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.RecyclerView.ViewHolder
import android.view.View
import android.view.ViewGroup
import android.widget.*
import com.kdanmobile.kmpdfkit.pdfcommon.Bookmark
import com.kdanmobile.reader.R
import com.kdanmobile.reader.screen.handler.PdfInfoHandler
import com.kdanmobile.reader.screen.handler.ThumbnailHandler
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers

class BookmarkAdapter(private val pdfInfoHandler: PdfInfoHandler, private val thumbnailHandler: ThumbnailHandler, private var bookmarks: Array<Bookmark>): RecyclerView.Adapter<BookmarkAdapter.BookmarkViewHolder>() {
    var bookmarkIndex = -1
        private set

    init {
        this.bookmarkIndex = getBookmarkIndex(pdfInfoHandler.getCurrentPage())
    }

    fun setCurrentPage(currentPage: Int) {
        val oldBookmarkIndex = bookmarkIndex
        if (oldBookmarkIndex != -1) {
            notifyItemChanged(oldBookmarkIndex, false)
        }
        bookmarkIndex = getBookmarkIndex(currentPage)
        if (bookmarkIndex != -1) {
            notifyItemChanged(bookmarkIndex, true)
        }
    }

    fun setBookIndex(bookmarkIndex: Int) {
        if (bookmarkIndex >= 0 && bookmarkIndex < bookmarks.size && bookmarkIndex != this.bookmarkIndex) {
            val oldBookmarkIndex = this.bookmarkIndex
            this.bookmarkIndex = bookmarkIndex
            notifyItemChanged(oldBookmarkIndex, false)
            notifyItemChanged(this.bookmarkIndex, true)
        }
    }

    private fun getBookmarkIndex(currentPage: Int): Int {
        for (index in 0 until bookmarks.size) {
            if (bookmarks[index].pageNum == currentPage) {
                return index
            }
        }
        return -1
    }

    fun setBookmarks(bookmarks: Array<Bookmark>) {
        this.bookmarks = bookmarks
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int {
        return bookmarks.size
    }

    fun getItem(position: Int): Bookmark? {
        return if (position >= 0 && position < bookmarks.size) bookmarks[position] else null
    }

    override fun onBindViewHolder(holder: BookmarkViewHolder, position: Int) {
        val bookmark = bookmarks[holder.adapterPosition]
        holder.msg.text = bookmark.title
        holder.page.text = (bookmark.pageNum + 1).toString()
        holder.onShowBorder(bookmarkIndex == holder.adapterPosition)
        holder.loadThumbSync(bookmark.pageNum)
    }

    override fun onBindViewHolder(holder: BookmarkViewHolder, position: Int, payloads: List<Any>) {
        if (payloads.isEmpty()) {
            onBindViewHolder(holder, position)
        } else {
            for (obj in payloads) {
                if (obj is Boolean) {
                    holder.onShowBorder(obj)
                }
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookmarkViewHolder {
        val view = View.inflate(parent.context, R.layout.item_bookmark, null)
        return BookmarkViewHolder(parent, view)
    }

    override fun onViewRecycled(holder: BookmarkViewHolder) {
        super.onViewRecycled(holder)
        holder.stopLoadThumbSync()
    }

    inner class BookmarkViewHolder(parent: ViewGroup, itemView: View): ViewHolder(itemView) {
        private val thumb: ImageView
        internal val page: TextView
        private val border: View
        internal val msg: TextView
        private val progress: ProgressBar
        private var disposable: Disposable? = null

        init {
            val idReaderBookmarkFl = itemView.findViewById<View>(R.id.tv_fragmentPdfReaderBookmarkLvItem_rl) as RelativeLayout
            val params = LinearLayout.LayoutParams((parent.measuredWidth - 20) / 2, (parent.measuredWidth - 20) * 9 / 14)
            params.setMargins(10, 5, 10, 5)
            idReaderBookmarkFl.layoutParams = params

            thumb = itemView.findViewById(R.id.iv_fragmentPdfReaderBookmarkLvItem_) as ImageView
            page = itemView.findViewById(R.id.tv_fragmentPdfReaderBookmarkLvItem_page) as TextView
            border = itemView.findViewById(R.id.v_fragmentPdfReaderBookmarkLvItem_)
            msg = itemView.findViewById(R.id.tv_fragmentPdfReaderBookmarkLvItem_name) as TextView
            progress = itemView.findViewById(R.id.pb_fragmentPdfReaderBookmarkLvItem_) as ProgressBar
        }

        internal fun onShowBorder(isShow: Boolean) {
            border.visibility = if (isShow) View.VISIBLE else View.GONE
            page.setBackgroundColor(ContextCompat.getColor(itemView.context, if (isShow) R.color.reader_thumbnail_background_selected else R.color.reader_thumbnail_background_normal))
            page.setTextColor(ContextCompat.getColor(itemView.context, if (isShow) R.color.reader_thumbnail_page_selected else R.color.reader_thumbnail_page_normal))
        }

        internal fun loadThumbSync(page: Int) {
            stopLoadThumbSync()

            disposable = Observable.create<Bitmap> { emitter ->
                val bitmap = thumbnailHandler.getPdfBitmap(page, 180, ThumbnailHandler.MODE_DAY, true)
                emitter.onNext(bitmap)
                emitter.onComplete()
            }
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe({
                        thumb.setImageBitmap(it)
                        thumb.invalidate()
                        progress.visibility = View.GONE
                    }, {
                        it.printStackTrace()
                    })
        }

        internal fun stopLoadThumbSync() {
            if (null != disposable && !disposable!!.isDisposed) {
                disposable?.dispose()
                disposable = null
            }
            thumb.setImageBitmap(null)
            thumb.invalidate()
            progress.visibility = View.VISIBLE
        }
    }
}
