package com.bomostory.sceneeditmodule

import android.app.AlertDialog
import android.app.ProgressDialog
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.os.Handler
import android.support.v4.app.DialogFragment
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.CompoundButton
import android.widget.SeekBar
import android.widget.Toast
import com.bomostory.sceneeditmodule.basicdata.DataParser
import com.bomostory.sceneeditmodule.basicdata.Music
import com.bomostory.sceneeditmodule.basicdata.Project
import com.bomostory.sceneeditmodule.basicdata.Scene
import com.bomostory.sceneeditmodule.share.ExportPdfDialog
import com.bomostory.sceneeditmodule.share.ShareDialog
import com.bomostory.sceneeditmodule.utils.MoviePlayer
import com.bomostory.sceneeditmodule.utils.MusicPlayer
import com.bomostory.sceneeditmodule.view.AudioTrackGroupView
import com.bomostory.sceneeditmodule.view.MovieSelectView
import com.example.exportmedia.MediaHelper
import com.example.tfat.myapplication.R
import com.google.gson.Gson
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_movie_edit.*
import java.io.File


class MovieEditActivity : AppCompatActivity(),
        DialogInterface.OnDismissListener,
        MusicSelectFragment.OnFragmentInteractionListener,
        MusicEditDialog.OnFragmentInteractionListener {

    override fun onFragmentInteraction(uri: Uri) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun onDismiss(dialog: DialogInterface?) {
        musicPlayer.stop()
        musicPlayer.release()

        delayedHide(100)
    }

    override fun onMusicPlayClick(path: String) {
        musicPlayer.pause()
        musicPlayer.clear()
        musicPlayer.add(path)
        musicPlayer.play()
    }

    override fun onMusicPauseClick() {
        musicPlayer.pause()
    }

    override fun onMusicImportClick(music: Music) {
        musics.add(music)
        moviePlayer.init()
        music.path?.let {
            moviePlayer.addMusic(it)
        }
        movieEditView.musics = musics

        val dialogFragment = supportFragmentManager.findFragmentByTag(MUSIC_SELECT_DIALOG_TAG) as DialogFragment
        dialogFragment.dismiss()
    }

    private val shareDialog = ShareDialog()

    private val mHideHandler = Handler()
    private val mHidePart2Runnable = Runnable {
        window.decorView.systemUiVisibility =
                View.SYSTEM_UI_FLAG_LOW_PROFILE or
                View.SYSTEM_UI_FLAG_FULLSCREEN or
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
    }
    private val mShowPart2Runnable = Runnable {
        supportActionBar?.show()
    }
    private val mHideRunnable = Runnable {
        hide()
    }

    private var project: Project? = null
        set(value) {
            field = value
            value?.let {
                it.story?.let {
                    movieEditView.story = it
                    scene = it.scenes[0]
                }
            }
        }

    private var scene: Scene? = null
        set(value) {
            field = value
            value?.let {
                movieView.scene = value
                movieEditView.scene = value
                moviePlayer.scene = value
            }
        }

    private var isLoop = false
        set(value) {
            field = value
            movieEditView.isLoop = value
        }

    private var currentAudioPosition = 0
        set(value) {
            field = value
            movieEditView.currentAudioPosition = value
        }


    private val moviePlayer = MoviePlayer()

    private val musicPlayer = MusicPlayer()

    private val musics = ArrayList<Music>()

    private val mediaHelper = MediaHelper()

    companion object {
        const val PROJECT_KEY = "project_key"
        const val MUSIC_SELECT_DIALOG_TAG = "music_select_dialog_tag"
        const val MUSIC_EDIT_DIALOG_TAG = "music_edit_dialog_tag"
        const val FPS: Int = 30
        private const val UI_ANIMATION_DELAY = 300
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_movie_edit)

        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        project = Gson().fromJson<Project>(intent.extras.getString(PROJECT_KEY), Project::class.java)

        movieEditView.onPlayClickListener = View.OnClickListener(this::playMovie)
        movieEditView.onPauseClickListener = View.OnClickListener(this::pauseMovie)
        movieEditView.onAddMusicClickListener = View.OnClickListener(this::addMusic)
        movieEditView.onEditMusicClickListener = View.OnClickListener(this::editMusic)
        movieEditView.onDeleteMusicClickListener = View.OnClickListener(this::deleteMusic)
        movieEditView.onSaveMovieClickListener = View.OnClickListener(this::onClickSaveAndShareBtn)
        movieEditView.onSeekBarChangeListener = object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                if (fromUser) {
                    moviePlayer.seekTo(progress)
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
            }
        }
        movieEditView.onMovieSelectListener = object : MovieSelectView.OnMovieSelectListener {
            override fun onMoveSelect(scene: Scene) {
                this@MovieEditActivity.scene = scene
            }
        }
        movieEditView.onAudioTrackSelectListener = object : AudioTrackGroupView.OnAudioTrackSelectListener {
            override fun onAudioTrackSelect(position: Int) {
                currentAudioPosition = position
            }
        }
        movieEditView.onAudioTrackScrollListener = object : AudioTrackGroupView.OnAudioTrackScrollListener {
            override fun onAudioTrackScroll(position: Int, scrollRatio: Double) {
                scene?.record?.period?.let {
                    musics[position].offsetTime = (it * scrollRatio).toLong()
                }
            }
        }
        movieEditView.onLoopSwitchChangedListener = CompoundButton.OnCheckedChangeListener { _, isChecked ->
            isLoop = isChecked
        }

        moviePlayer.moviePlayListener = object : MoviePlayer.OnMoviePlayListener {
            override fun onMoviePlayComplete() {
                movieEditView.isBtnPanelEnable = true
            }

            override fun onMoviePlayViewUpdate(x: Int) {
                movieView.x = x
            }

            override fun onMoviePlayTimeUpdate(time: Long) {
                movieEditView.playTime = time
            }
        }

        mediaHelper.init(this)
    }

    override fun onPostResume() {
        super.onPostResume()
        delayedHide(100)
    }

    private fun delayedHide(delayMillis: Int) {
        mHideHandler.removeCallbacks(mHideRunnable)
        mHideHandler.postDelayed(mHideRunnable, delayMillis.toLong())
    }

    private fun hide() {
        supportActionBar?.hide()
        mHideHandler.removeCallbacks(mShowPart2Runnable)
        mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY.toLong())
    }

    private fun playMovie(view: View) {
        moviePlayer.play()
        movieEditView.isBtnPanelEnable = false
    }

    private fun pauseMovie(view: View) {
        moviePlayer.pause()
        movieEditView.isBtnPanelEnable = true
    }

    private fun addMusic(view: View) {
        val libraryPaths = ArrayList<String>()

        project?.let {
            val assetFolder = it.assetFolder.path
            it.themeAssetIndex.contains.music.values.forEach {
                libraryPaths.add("$assetFolder/$it")
            }
        }

        val musicSource = DataParser.parseMusicSource(contentResolver, libraryPaths)
        val musicSelectDialog = MusicSelectDialog.newInstance(Gson().toJson(musicSource))
        musicSelectDialog.show(supportFragmentManager, MUSIC_SELECT_DIALOG_TAG)
    }

    private fun editMusic(view: View) {
        Log.d("Debug", "edit music track $currentAudioPosition")

        val musicEditDialog = MusicEditDialog.newInstance("", "")
        musicEditDialog.show(supportFragmentManager, MUSIC_EDIT_DIALOG_TAG)
    }

    private fun deleteMusic(view: View) {
        if (currentAudioPosition in 0 until musics.size) {
            moviePlayer.init()
            musics[currentAudioPosition].path?.let {
                moviePlayer.removeMusic(it)
            }

            musics.removeAt(currentAudioPosition)

            movieEditView.musics = musics
        }
    }

    private fun onClickSaveAndShareBtn(view: View) {
        shareDialog.apply {
            name = project?.name ?: ""
            author = project?.author ?: ""
            onClickBomo = Runnable { saveMovie() }
            onClickExportPdf = Runnable { onClickExportPdf() }
        }.show(supportFragmentManager)
    }

    private fun onClickExportPdf() {
        ExportPdfDialog().also { exportPdfDialog ->
            exportPdfDialog.image1Path = project?.scene1File?.path ?: ""
            exportPdfDialog.image2Path = project?.scene2File?.path ?: ""
            exportPdfDialog.onClickPrint = Runnable {
                when (exportPdfDialog.type) {
                    ExportPdfDialog.Type.Standard -> {
                        val name = "standard_${project?.name}_${System.currentTimeMillis()}.pdf"
                        if (!Config.PDF_FOLDER.exists()) {
                            Config.PDF_FOLDER.mkdirs()
                        }
                        val file = File(Config.PDF_FOLDER, name)
                        file.createNewFile()
                        val observable = PdfMaker.makeStandard(this@MovieEditActivity, project!!, file)
                        Pair(file, observable)
                    }
                    ExportPdfDialog.Type.Booklet -> {
                        val name = "booklet_${project?.name}_${System.currentTimeMillis()}.pdf"
                        if (!Config.PDF_FOLDER.exists()) {
                            Config.PDF_FOLDER.mkdirs()
                        }
                        val file = File(Config.PDF_FOLDER, name)
                        file.createNewFile()
                        val observable = PdfMaker.makeBooklet(this@MovieEditActivity, project!!, file)
                        Pair(file, observable)
                    }
                }.apply {
                    exportPdfFile(second, Runnable {
                        exportPdfDialog.dismiss()
                    }, Runnable {
                        showPdfExportCompleteDialog(first)
                    })
                }
            }
        }.show(supportFragmentManager)
    }

    private fun saveMovie() {
        val scaledWidth = resources.getDimensionPixelSize(R.dimen.movie_width)
        val scaleHeight = resources.getDimensionPixelSize(R.dimen.movie_height)

        val pd = ProgressDialog(this).apply {
            val t = scene?.record?.period ?: 0
            max = (t / 33).toInt()
            setMessage("progressing")
            setCancelable(false)
        }

        val fileName = "test${System.currentTimeMillis()}.mp4"
        val outputFile = File(Environment.getExternalStorageDirectory(), fileName)
        val project = project ?: return

        SuperMovieMaker().make(
                outputFile,
                project,
                musics,
                scaledWidth,
                scaleHeight,
                mediaHelper)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe {
                    pd.show()
                    delayedHide(100)
                }
                .doFinally { pd.dismiss() }
                .subscribe({
                    pd.setMessage(it)
                }, {
                    val msg = """
                    Error:
                    ${it.message}
                """.trimIndent()
                    AlertDialog.Builder(this).setMessage(msg).show()
                    delayedHide(100)
                }, {
                    AlertDialog.Builder(this)
                            .setMessage("Complete")
                            .setPositiveButton("Play") { _, _ ->
                                val uri = Uri.parse(outputFile.absolutePath)
                                val intent = Intent(Intent.ACTION_VIEW, uri).apply {
                                    setDataAndType(uri, "video/mp4")
                                }
                                if (intent.resolveActivity(packageManager) != null) {
                                    Intent.createChooser(intent, "").apply {
                                        startActivity(this)
                                    }
                                } else {
                                    Toast.makeText(this, "No app can play video", Toast.LENGTH_SHORT).show()
                                }
                            }.show()
                    delayedHide(100)
                })
    }

    private fun exportPdfFile(observable: Observable<Float>, onFinally: Runnable, onComplete: Runnable) {
        val pd = ProgressDialog(this@MovieEditActivity).apply {
            setCancelable(false)
        }
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe { pd.show() }
                .doFinally {
                    pd.dismiss()
                    onFinally.run()
                }
                .subscribe({
                    val progress = (it * 100).toInt()
                    val msg = if (progress >= 100) {
                        "processing ..."
                    } else {
                        "$progress%"
                    }
                    pd.setMessage(msg)
                }, {
                }, {
                    onComplete.run()
                })
    }

    private fun showPdfExportCompleteDialog(file: File) {
        AlertDialog.Builder(this@MovieEditActivity)
                .setMessage("Complete")
                .setPositiveButton("View") { _, _ ->
                    val uri = Uri.parse(file.absolutePath)
                    val intent = Intent(Intent.ACTION_VIEW, uri).apply {
                        setDataAndType(uri, "application/pdf")
                    }
                    if (intent.resolveActivity(packageManager) != null) {
                        Intent.createChooser(intent, "").apply {
                            startActivity(this)
                        }
                    } else {
                        Toast.makeText(this@MovieEditActivity, "No app can view pdf", Toast.LENGTH_SHORT).show()
                    }
                }.show()
    }

}