package com.mime.dualscreenview.activity

import android.app.ActivityOptions
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.hardware.display.DisplayManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.view.View.*
import android.webkit.WebView
import android.widget.ArrayAdapter
import android.widget.ImageButton
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatButton
import com.google.gson.Gson
import com.lge.display.DisplayManagerHelper
import com.mime.dualscreenview.R
import com.mime.dualscreenview.common.Blog
import com.mime.dualscreenview.dialog.StyleSelectInterface
import com.mime.dualscreenview.dialog.Stylez
import com.mime.dualscreenview.dto.BookPageInfo
import com.mime.dualscreenview.dto.BookPageInfos
import com.mime.dualscreenview.dto.HistoryItem
import com.mime.dualscreenview.dto.LastInfo
import com.mime.dualscreenview.view.PagedTextLayout
import com.mime.dualscreenview.view.PagedTextViewInterface
import com.mime.dualscreenview.view.TouchArea
import com.mime.dualscreenview.webcontents.BaseWebContentsViewer
import com.mime.dualscreenview.webcontents.MainControllInterface
import com.mime.dualscreenview.webcontents.contentsinfo.Booktoki
import com.mime.dualscreenview.webcontents.contentsinfo.GotoSomeWhere
import io.realm.kotlin.Realm
import io.realm.kotlin.RealmConfiguration
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.copyFromRealm
import io.realm.kotlin.ext.query
import java.lang.System.currentTimeMillis
import java.net.URI
import java.text.SimpleDateFormat
import java.util.Date


class Intro : Base() , MainControllInterface, PagedTextViewInterface {

    private var displayManagerHelper: DisplayManagerHelper? = null

    // This callbacks where receive events from the cover
    private var coverDisplayCallback: MainCoverDisplayCallback? = null
    private var smartCoverCallback: MainSmartCoverCallback? = null

    // Save previous state of dual screens
    private var prevDualScreenState = DisplayManagerHelper.STATE_UNMOUNT

    private var isLGDualScreen: Boolean = false
    private lateinit var mBaseWebContentsViewer : BaseWebContentsViewer
    var lastInfo : LastInfo? = null



    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        Blog.LOGD(log= "onConfigurationChanged ${this::class.java.name} >> newConfig ${newConfig}")
        mBaseWebContentsViewer.webview.reload()
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Blog.LOGD(log= "onCreate ${this::class.java.name} >> savedInstanceState ${savedInstanceState}")
        setContentView(R.layout.intro)

        mBaseWebContentsViewer = BaseWebContentsViewer(findViewById<WebView>(R.id.menu_web),this)
        try {
            // Try to construct the DisplayMangerHelper.
            // If it isn't successful, this device isn't LG dual screens
            displayManagerHelper = DisplayManagerHelper(applicationContext)
            coverDisplayCallback = MainCoverDisplayCallback()
            smartCoverCallback = MainSmartCoverCallback()

            // Register the callbacks for covers
            displayManagerHelper?.registerCoverDisplayEnabledCallback(
                applicationContext.packageName,
                coverDisplayCallback
            )
            displayManagerHelper?.registerSmartCoverCallback(smartCoverCallback)
            isLGDualScreen = true
        } catch (e: Exception) {
            isLGDualScreen = false
            Log.e(TAG, "This device isn't LG dual screens", e)
        }

        findViewById<ImageButton>(R.id.btn_list).setOnClickListener { v ->
            mBaseWebContentsViewer?.findListItem {result ->
                if (result != null && "null".equals(result) == false && result?.length ?: 0 > 10) {
                    try {
                        Gson().fromJson(result, BookPageInfos::class.java)?.let{
                            showList(it)
                        }
                    } catch (e : Exception) {

                    }
                }
            }
        }

        findViewById<View>(R.id.btn_rotate).setOnClickListener { v->
           switcvhOrient()
        }
        findViewById<View>(R.id.btn_setting).setOnClickListener { v->
            showStyleList()
        }
        findViewById<View>(R.id.btn_history).setOnClickListener { v->
            var realm = openRealm()
            realm.query<HistoryItem>()?.find()?.let {
                showHistory(realm.copyFromRealm(it))
            }
            realm.close()
        }
        findViewById<View>(R.id.btn_home).setOnClickListener { v->
            pagedTextLayout?.visibility = GONE
            mBaseWebContentsViewer.loadContents(Booktoki())
        }


    }

    fun reloadLastInfo() {
        val realm = openRealm()
        try { lastInfo = realm?.query<LastInfo>()?.find()?.last()?.copyFromRealm() } catch (e : Exception) { }
        val configuration: Configuration = getResources().getConfiguration()
        if(lastInfo != null && lastInfo?.displayOrientation != configuration.orientation) {
            findViewById<View>(R.id.btn_rotate).performClick()
        }
        realm.close()
    }

    fun reloadTo(lastInfo: LastInfo?) {
        findViewById<WebView>(R.id.menu_web)?.postDelayed({
            if (lastInfo != null) {
                mBaseWebContentsViewer.loadLastInfo(lastInfo!!)
            } else {
                mBaseWebContentsViewer.loadContents(Booktoki())
            }
        },200L)
    }
    override fun onResume() {
        super.onResume()
        reloadLastInfo()
        reloadTo(lastInfo)
    }
    fun switcvhOrient(){
        val configuration: Configuration = getResources().getConfiguration()
        setRequestedOrientation(
            if(configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE }
            else {ActivityInfo.SCREEN_ORIENTATION_PORTRAIT}
        )
    }

    fun showHistory(infos: List<HistoryItem>) {
        val builderSingle: AlertDialog.Builder = AlertDialog.Builder(this@Intro)
        builderSingle.setTitle("${currentTitle} : ${currentChapter} -> Select One ")
        val arrayAdapter =
            ArrayAdapter<String>(this@Intro, android.R.layout.select_dialog_singlechoice)
        for (item in infos) {
            arrayAdapter.addAll(item.title)
        }



        builderSingle.setNegativeButton("cancel",
            DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() })

        builderSingle.setAdapter(arrayAdapter,
            DialogInterface.OnClickListener { dialog, which ->
                val strName = arrayAdapter.getItem(which)
                val item = infos.get(which)
                val builderInner: AlertDialog.Builder = AlertDialog.Builder(this@Intro)
                builderInner.setMessage(strName)
                builderInner.setTitle("${infos.get(which).title}로 이동 고고!?")
                builderInner.setPositiveButton("Ok",
                    DialogInterface.OnClickListener {
                            dialog, which ->
                        reloadTo(item.makeLastInfo())
                        dialog.dismiss()
                    })
                builderInner.setNeutralButton("삭제",
                    DialogInterface.OnClickListener {
                            dialog, which ->
                        var realm = openRealm()
                        realm?.writeBlocking {
                            this.query<HistoryItem>().query("title == '${item.title}'", ).find()?.last()?.let{
                                this.delete(it)
                            }
                        }
                        realm.close()
                        dialog.dismiss()
                    })
                builderInner.setNegativeButton("취소",
                    DialogInterface.OnClickListener {
                            dialog, which ->
                        dialog.dismiss()
                    })
                builderInner.show()
            })
        var ddddd= builderSingle.create()
        ddddd.setOnShowListener { d->
            (d as? AlertDialog)?.let{
                it.listView?.setSelection(currentChapter)
            }
        }

        ddddd.show()
    }

    fun showList(infos: BookPageInfos) {
        val builderSingle: AlertDialog.Builder = AlertDialog.Builder(this@Intro)
        builderSingle.setTitle("${currentTitle} : ${currentChapter} -> Select One ")
        val arrayAdapter =
            ArrayAdapter<String>(this@Intro, android.R.layout.select_dialog_singlechoice)
        arrayAdapter.addAll(infos.getTitleArray())


        builderSingle.setNegativeButton("cancel",
            DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() })

        builderSingle.setAdapter(arrayAdapter,
            DialogInterface.OnClickListener { dialog, which ->
                val strName = arrayAdapter.getItem(which)
                val item = infos.list?.get(which)
                val builderInner: AlertDialog.Builder = AlertDialog.Builder(this@Intro)
                builderInner.setMessage(strName)
                builderInner.setTitle("Your Selected Item is")
                builderInner.setPositiveButton("Ok",
                    DialogInterface.OnClickListener { dialog, which ->
//                    mBaseWebContentsViewer?.webview?.loadUrl()
                        moveTo(item)
                        dialog.dismiss()
                    }
                )
                builderInner.show()
            })
        var ddddd= builderSingle.create()
        ddddd.setOnShowListener { d->
            (d as? AlertDialog)?.let{
                it.listView?.setSelection(currentChapter)
            }
        }

        ddddd.show()
    }

    private fun moveTo(item: BookPageInfo?) {
        item?.link?.let {newPath ->
            mBaseWebContentsViewer?.webview?.url?.let{currentUrl ->
                Uri.parse(currentUrl)?.lastPathSegment?.let {
                    currentUrl.replace(it,newPath)?.let {
                        mBaseWebContentsViewer?.webview?.loadUrl(it)
                    }
                }
            }
        }


    }

    fun showStyleList() {
        var mStylez = Stylez(this@Intro)
        mStylez.styleSelectInterface = object : StyleSelectInterface {
            override fun onSelectStyle(bgColor: String, textColor: String) {
                pagedTextLayout?.setColorStyle(arrayOf(textColor,bgColor))
            }
        }
        mStylez.show()
    }


    override fun onDestroy() {
        // Remove all callbacks when this activity is destroyed
        displayManagerHelper?.unregisterCoverDisplayEnabledCallback(applicationContext.packageName)
        displayManagerHelper?.unregisterSmartCoverCallback(smartCoverCallback)
        super.onDestroy()
    }

    /**
     * Convert cover display states to string to serve for logging
     *
     * @param state is the value integer of state
     * @return a string for this state
     */
    private fun coverDisplayStateToString(state: Int): String {
        return when (state) {
            DisplayManagerHelper.STATE_UNMOUNT -> "STATE_UNMOUNT"
            DisplayManagerHelper.STATE_DISABLED -> "STATE_DISABLED"
            DisplayManagerHelper.STATE_ENABLED -> "STATE_ENABLED"
            else -> "UNKNOWN_STATE"
        }
    }

    /**
     * Convert smart cover display states to string to serve for logging
     *
     * @param state is the value integer of state
     * @return a string for this state
     */
    private fun smartCoverStateToString(state: Int): String {
        return when (state) {
            DisplayManagerHelper.STATE_COVER_OPENED -> "STATE_COVER_OPENED"
            DisplayManagerHelper.STATE_COVER_CLOSED -> "STATE_COVER_CLOSED"
            DisplayManagerHelper.STATE_COVER_FLIPPED_OVER -> "STATE_COVER_FLIPPED_OVER"
            else -> "UNKNOWN_STATE"
        }
    }

    /**
     * Navigate to the second screen.
     *
     * See more at https://developer.android.com/guide/topics/ui/foldables?#using_secondary_screens
     */
    private fun toSecondScreen(screenNumStr : String) {

        var screenNum = screenNumStr.toInt()
        // DisplayManager manages the properties of attached displays.
        val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager

        // List displays was attached
        val displays = displayManager.displays

        if (displays.size > screenNum) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // Activity options are used to select the display screen.
                val options = ActivityOptions.makeBasic()
                // Select the display screen that you want to show the second activity
                options.launchDisplayId = displays[screenNum].displayId

                // To display on the second screen that your intent must be set flag to make
                // single task (combine FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_NEW_TASK)
                // or you also set it in the manifest (see more at the manifest file)
                startActivity(
                    Intent(this@Intro, Main::class.java).apply {

                    },
                    options.toBundle()
                )
            }
        } else {
            Toast.makeText(this, "Not found the second screen", Toast.LENGTH_SHORT).show()
        }
    }

    private inner class MainCoverDisplayCallback : DisplayManagerHelper.CoverDisplayCallback() {
        override fun onCoverDisplayEnabledChangedCallback(state: Int) {
            displayManagerHelper?.coverDisplayState?.let {
                Log.i(TAG, "Current DualScreen Callback state: ${coverDisplayStateToString(it)}")
            }
            if (prevDualScreenState != state) {
                when (state) {
                    DisplayManagerHelper.STATE_UNMOUNT -> {
                        Log.i(TAG, "Changed DualScreen State to STATE_UNMOUNT")
                    }
                    DisplayManagerHelper.STATE_DISABLED -> {
                        Log.i(TAG, "Changed DualScreen State to  STATE_DISABLED")
                    }
                    DisplayManagerHelper.STATE_ENABLED -> {
//                        toSecondScreen()
                        Log.i(TAG, "Changed DualScreen State to  STATE_ENABLED")
                    }
                }
                prevDualScreenState = state
            }
        }
    }

    private inner class MainSmartCoverCallback : DisplayManagerHelper.SmartCoverCallback() {
        override fun onTypeChanged(type: Int) {
            Log.i(TAG, "SmartCoverCallback type: ${displayManagerHelper?.coverType}")
        }

        override fun onStateChanged(state: Int) {
            displayManagerHelper?.coverState?.let {
                Log.i(TAG, "Current SmartCoverCallback state: ${smartCoverStateToString(it)}")
            }
            when (state) {
                DisplayManagerHelper.STATE_COVER_OPENED -> {
                    Log.i(TAG, "Received SmartCoverCallback is STATE_COVER_OPENED")
                }
                DisplayManagerHelper.STATE_COVER_CLOSED -> {
                    Log.i(TAG, "Received SmartCoverCallback is STATE_COVER_CLOSED")
                }
                DisplayManagerHelper.STATE_COVER_FLIPPED_OVER -> {
                    Log.i(TAG, "Received SmartCoverCallback is STATE_COVER_FLIPPED_OVER")
                }
            }
        }
    }
    var pagedTextLayout : PagedTextLayout? = null;

    var onNextClickAction: GotoSomeWhere? = null
    override fun showNextBtn(find : Boolean , onClickAction: GotoSomeWhere) {
        onNextClickAction = onClickAction
        findViewById<AppCompatButton>(R.id.btn_right)?.let{
            it.text = "다음 페이지"
            it.setOnClickListener {
                actionNextEvent()
            }
            it.visibility= if(find) VISIBLE else GONE
        }
    }

    fun actionNextEvent() {
        if (pagedTextLayout != null && pagedTextLayout!!.visibility == View.VISIBLE && pagedTextLayout!!.size() > 0 && (pagedTextLayout!!.current() < pagedTextLayout!!.size() - 1) ) {
            pagedTextLayout!!.doNext()
            updateLastInfo(pagedTextLayout!!)
        }else {
            onNextClickAction?.let { it() }
        }
    }
    var onPrevClickAction: GotoSomeWhere? = null
    override fun showPrevBtn(find : Boolean, onClickAction: GotoSomeWhere) {
        onPrevClickAction = onClickAction
        findViewById<AppCompatButton>(R.id.btn_left)?.let{
            it.text = "이전 페이지"
            it.setOnClickListener {
                actionPrevEvent()
            }
            it.visibility= if(find) VISIBLE else GONE
        }
    }


    fun actionPrevEvent() {
        if (pagedTextLayout != null && pagedTextLayout!!.visibility == View.VISIBLE && pagedTextLayout!!.size() > 0 && pagedTextLayout!!.current() > 0 ) {
            pagedTextLayout!!.doPrev()
            updateLastInfo(pagedTextLayout!!)
        } else {
            onPrevClickAction?.let{ it() }
        }
    }

    override fun onBackPressed() {
        var layer = findViewById<PagedTextLayout>(R.id.paged_layer)

        if (!didBackPress) {
            firstBackPress()
            return
        }

        if (layer != null && layer.visibility == View.VISIBLE) {
            didBackPress = false
            layer.visibility = GONE
            onTouch(TouchArea.Center)
            return
        }

        if (mBaseWebContentsViewer.webview.canGoBack()) {
            mBaseWebContentsViewer.webview.goBack()
            return
        }

        if (!didBackPress) {
            firstBackPress()
            return
        }
        finish()
        didBackPress = false
    }


    override fun showAlert(alert: String) {
        Log.i(TAG,"showAlert >> " + alert)
    }

    override fun onLoadedContents(contents: String) {
        pagedTextLayout = null;
        findViewById<PagedTextLayout>(R.id.paged_layer).apply {
            if (contents != null) {
                pagedTextLayout = this
                visibility = VISIBLE
                mPagedTextViewInterface = this@Intro
                setText(contents.replace("\\n", System.getProperty("line.separator")))
                setTextSize(22f)
                if(lastInfo != null && lastInfo!!.pageUrl.equals(mBaseWebContentsViewer.webview.url)) {
                    this@Intro.findViewById<ProgressBar>(R.id.progress)?.visibility = VISIBLE
                    pagedTextLayout?.postDelayed({
                        next(lastInfo!!.pageIndex)
                        pagedTextLayout?.post {
                            this@Intro.findViewById<ProgressBar>(R.id.progress)?.visibility = GONE
                        }
                    },1000)
                }
                forceUpdateUI()
            }
        }

        Log.i(TAG,"onLoadedContents >> " + contents)
    }

    var currentTitle : String = ""
    var currentChapter : Int = 0

    override fun onFindTitle(contents: String) {
        findViewById<TextView>(R.id.textView).text = contents
        var testRegex = """[^0-9]""".toRegex();
        Blog.LOGI(TAG,"onFindTitle >> " + contents + "   :::  ${testRegex.replace(contents,"")}")
        if(contents.contains("-")) {
            currentTitle = contents.split("-")[0]
            try {
                currentChapter = testRegex.replace(contents.split("-")[1],"").toInt()
            } catch (e : Exception) {
                currentChapter = 0
            }
        } else if(testRegex.replace(contents,"").length > 0){
            currentChapter = testRegex.replace(contents,"").toInt()
            currentTitle = contents.split(testRegex.replace(contents,""))[0]
        } else {
            val dateFormat = "yyyyMMdd-HH"
            val date = Date(currentTimeMillis())
            val simpleDateFormat = SimpleDateFormat(dateFormat)
            currentTitle = simpleDateFormat.format(date)
        }

    }

    override fun onStartLoad() {
        findViewById<ProgressBar>(R.id.progress).visibility = VISIBLE
    }

    override fun completePageLoad(lastInfo: LastInfo) {
        val configuration: Configuration = getResources().getConfiguration()

        if(this.lastInfo == null || !(this.lastInfo?.pageUrl.equals(lastInfo?.pageUrl)) || this.lastInfo?.displayOrientation != configuration?.orientation) {
            lastInfo.displayOrientation = configuration?.orientation ?: ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
            saveLastInfo(lastInfo)
        }
        findViewById<ProgressBar>(R.id.progress).visibility = GONE
    }

    fun saveLastInfo(lastInfo: LastInfo) {
        val realm = openRealm()
        if((realm.query<LastInfo>()?.count()?.find() ?: 0) > 0) {
            realm.writeBlocking {
                this.query<LastInfo>()?.find()?.last()?.let{
                    it.pageUrl = lastInfo.pageUrl
                    it.title = currentTitle
                    it.chapter = currentChapter
                    it.pageIndex = lastInfo.pageIndex
                    it.contentsName = lastInfo.contentsName
                    it.displayOrientation = lastInfo.displayOrientation
                    this@Intro.lastInfo = copyFromRealm(it)
                }
            }
        } else {
            realm.writeBlocking {
                copyToRealm(lastInfo)
            }
        }
        Blog.LOGD(log ="Successfully opened realm: ${realm.configuration.name}")
        realm.close()
    }

    fun updateLastInfo(pagedTextLayout: PagedTextLayout) {
        val configuration: Configuration = getResources().getConfiguration()
        val realm = openRealm()
        realm.writeBlocking {
            this.query<LastInfo>()?.find()?.last()?.let{
                it.displayOrientation = configuration.orientation
                it.title = currentTitle
                it.chapter = currentChapter
                it.pageIndex = pagedTextLayout.current()
                this@Intro.lastInfo = copyFromRealm(it)
            }
            if (currentTitle.length > 0 && currentChapter > 0) {
                this@Intro.lastInfo?.makeHistoryItem()?.let{
                    copyToRealm(it, UpdatePolicy.ALL)
                }
            }
        }

        Blog.LOGD(log ="Successfully opened realm: ${realm.configuration.name}")
        realm.close()
    }
    override fun onKeyClick(keyCode: Int): Boolean {
        when(keyCode) {
            KeyEvent.KEYCODE_VOLUME_DOWN ->{actionNextEvent()}
            KeyEvent.KEYCODE_VOLUME_UP ->{actionPrevEvent()}
            KeyEvent.KEYCODE_VOLUME_MUTE -> {actionNextEvent()}

        }
        return super.onKeyClick(keyCode)
    }

    override fun onTouch(touchArea: TouchArea) {
        Blog.LOGD(log="onTouch")
        when (touchArea) {
            TouchArea.Center-> {
                findViewById<View>(R.id.btn_right).visibility = VISIBLE
                findViewById<View>(R.id.btn_left).visibility = VISIBLE
                findViewById<View>(R.id.btn_setting).visibility = VISIBLE

                findViewById<View>(R.id.textView).visibility = VISIBLE
                findViewById<View>(R.id.btn_home).visibility = VISIBLE
                findViewById<View>(R.id.btn_list).visibility = VISIBLE
                findViewById<View>(R.id.btn_history).visibility = VISIBLE
                findViewById<View>(R.id.btn_rotate).visibility = VISIBLE

            }
            TouchArea.Right -> {
                actionNextEvent()
            }
            TouchArea.Left-> {
                actionPrevEvent()
            }
            else -> {

            }
        }


    }

    override fun onSwipeLeft() {
        Blog.LOGD(log="onSwipeLeft")
        actionNextEvent()

    }

    override fun onSwipeRight() {
        Blog.LOGD(log="onSwipeRight")
        actionPrevEvent()
    }


    override fun onTimeoverTouch() {
        Blog.LOGD(log="onTimeoverTouch")
        findViewById<View>(R.id.btn_right).visibility = GONE
        findViewById<View>(R.id.btn_left).visibility = GONE
        findViewById<View>(R.id.btn_setting).visibility = GONE

        findViewById<View>(R.id.textView).visibility = GONE
        findViewById<View>(R.id.btn_home).visibility = GONE
        findViewById<View>(R.id.btn_list).visibility = GONE
        findViewById<View>(R.id.btn_history).visibility = GONE
        findViewById<View>(R.id.btn_rotate).visibility = GONE

    }

    companion object {
        private const val TAG = "DualScreenStatus"
    }
}