package com.example.exportmedia

import android.graphics.Bitmap
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream

class MovieMaker(
        private val mediaHelper: MediaHelper,
        private val imageDir: String,
        private val fps: Int,
        private val audioStartTime: String,
        private val audioFile: File
) {

    private constructor(builder: Builder) : this(
            builder.mediaHelper,
            builder.imageDir,
            builder.fps,
            builder.audioStartTime,
            builder.audioFile
    )

    fun output(file: File): Observable<String> {
        return Observable.create {
            mediaHelper.execute(arrayOf(
                    "-framerate", fps.toString(),
                    "-i", imageDir + File.separator + "image%d.png",
                    "-itsoffset", audioStartTime,
                    "-i", audioFile.path,
                    "-c:v", "libx264",
                    "-pix_fmt", "yuv420p",
                    "-c:a", "aac",
                    "-async", "1",
                    "-y", "-shortest", file.path
            ), object : MediaCallBack {
                override fun onExecuteSuccess(message: String?) {
                    message?.let { it1 -> it.onNext(it1) }
                }

                override fun onExecuteFailed(message: String?) {
                    it.onError(Throwable(message))
                }

                override fun onExecuteFinish() {
                    it.onComplete()
                    clear()
                }
            })
        }
    }

    private fun clear() {
        val folder = File(imageDir)
        if (folder.isDirectory) {
            for (file in folder.listFiles()) {
                file.delete()
            }
        }
    }

    class Builder(internal val mediaHelper: MediaHelper) {

        var fps = 1

        var audioStartTime = "00:00:00"

        lateinit var audioFile: File

        internal val imageDir = mediaHelper.context?.filesDir?.path!! + File.separator + "EncodeImage"

        fun addImage(index: Int, bitmap: Bitmap) {
            Observable.create<String> {
                val byteArrayOutputStream = ByteArrayOutputStream()
                val file = File(imageDir, "image$index.png")
                val fileOutputStream = FileOutputStream(file, false)

                try {
                    bitmap.compress(Bitmap.CompressFormat.PNG, 0, byteArrayOutputStream)
                    val byteArray = byteArrayOutputStream.toByteArray()
                    fileOutputStream.write(byteArray)
                } catch (e: Exception) {
                    it.onError(e)
                } finally {
                    fileOutputStream.flush()
                    fileOutputStream.close()
                    bitmap.recycle()
                }

                it.onNext(file.path)
                it.onComplete()
            }
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe()
        }

        fun build() = MovieMaker(this)
    }
}