package com.example.gengmei_flutter_plugin

import android.Manifest
import android.annotation.TargetApi
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.provider.MediaStore
import android.support.v4.content.FileProvider
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import com.example.gengmei_flutter_plugin.result.ResultManager
import com.example.gengmei_flutter_plugin.sharedPrefernces.SharedManager
import com.example.gengmei_flutter_plugin.utils.DebugUtil
import com.example.gengmei_flutter_plugin.utils.addTo
import com.example.myimagepicker.luban.Luban
import com.example.myimagepicker.repository.ImageRespository
import io.flutter.plugin.common.*
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
import io.reactivex.disposables.CompositeDisposable
import java.io.File
import kotlin.collections.ArrayList
import kotlin.collections.HashMap

class GengmeiFlutterPlugin : MethodCallHandler {

    var disposable = CompositeDisposable()
    var result: Result? = null
    var resultKey = 0L

    var gotoNativeCameraKey = 0L;


    var isAdded = false;
    private var record: HashMap<String, ArrayList<HashMap<String, Any>>>? = null;
    var nativeImage: File? = null
    var isTaskingExectured: Boolean = false;

    companion object {
        const val IMAGE_PICKER = "scan_image_picker"
        const val NATIVE_CAMERA = "native_camera"
        const val QUIT_PAGE = "quit_page"
        const val AI_CAMERA = "ai_camera"
        const val DETECT_FACE = "detectPic"
        const val SAVE_STRING_SHARED = "SAVE_STRING_SHARED"
        const val SAVE_INT_SHARED = "SAVE_INT_SHARED"
        const val SAVE_FLOAT_SHARED = "SAVE_FLOAT_SHARED"
        const val SAVE_BOOLEAN_SHARED = "SAVE_BOOLEAN_SHARED"
        const val SAVE_STRINGLIST_SHARED = "SAVE_STRINGLIST_SHARED"

        const val GET_STRING_SHARED = "GET_STRING_SHARED"
        const val GET_INT_SHARED = "GET_INT_SHARED"
        const val GET_FLOAT_SHARED = "GET_FLOAT_SHARED"
        const val GET_BOOLEAN_SHARED = "GET_BOOLEAN_SHARED"
        const val GET_STRINGLIST_SHARED = "GET_STRINGLIST_SHARED"
        const val PREMISSION = 10090
        //相机请求码
        private val CAMERA_REQUEST_CODE = 2
        private val CAMERA_REQUEST_CODE_AI = 10012

        //剪裁请求码
        private val CROP_REQUEST_CODE = 3
        lateinit var resign: Registrar;
        var listener: EventChannel.EventSink? = null
        @JvmStatic
        fun registerWith(registrar: Registrar) {
            if (registrar.activity() == null) {
                return
            }
            resign = registrar;
            val gengmeiFlutterPlugin = GengmeiFlutterPlugin();
            val channel = MethodChannel(registrar.messenger(), "gengmei_flutter_plugin")
            channel.setMethodCallHandler(gengmeiFlutterPlugin)
            val eventChannel = EventChannel(registrar.messenger(), "gengmei_flutter_plugin_event")
            eventChannel.setStreamHandler(object : EventChannel.StreamHandler {
                override fun onListen(p0: Any?, p1: EventChannel.EventSink?) {
                    listener = p1;
                }

                override fun onCancel(p0: Any?) {
                    print("ON CANCEL !!!   ");
                    listener = null;
                }
            })
        }
    }


    private fun gotoNativeCamera(providerString: String) {
        nativeImage = File(resign.activity().getExternalFilesDir(Environment.DIRECTORY_PICTURES), "/GengmeiAi${System.currentTimeMillis()}.jpg");
        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {   //如果在Android7.0以上,使用FileProvider获取Uri
            intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            val contentUri = FileProvider.getUriForFile(resign.activeContext().applicationContext, providerString, nativeImage!!);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
        } else {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(nativeImage));
        }
        resign.activity().startActivityForResult(intent, CAMERA_REQUEST_CODE);
    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        resultKey++
        ResultManager.getInstance().addResult(resultKey, result);
        when (call.method) {
            IMAGE_PICKER -> checkPermission(object : PermissionListener {
                override fun OK() {
                    val result = resultKey;
                    ScanImage(result)
                }
            })
            NATIVE_CAMERA -> {
                gotoNativeCameraKey = resultKey;
                checkPermission(object : PermissionListener {
                    override fun OK() {
                        gotoNativeCamera(call.argument<String>("authority")!!)
                    }
                })
            }
            SAVE_STRING_SHARED -> {
                val result = resultKey;
                SharedManager.getInstance(resign.activity().applicationContext).saveString(call.argument<String>("key")!!, call.argument<String>("value")!!)
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, it);
                        }, DebugUtil::printStackTrace).addTo(disposable)
            }
            SAVE_INT_SHARED -> {
                val result = resultKey;
                SharedManager.getInstance(resign.activity().applicationContext).saveInt(call.argument<String>("key")!!, call.argument<Int>("value")!!)
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, it);
                        }, DebugUtil::printStackTrace).addTo(disposable)
            }
            SAVE_FLOAT_SHARED -> {
                val result = resultKey;
                SharedManager.getInstance(resign.activity().applicationContext).saveFloat(call.argument<String>("key")!!, call.argument<Float>("value")!!)
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, it);
                        }, DebugUtil::printStackTrace).addTo(disposable)
            }
            SAVE_BOOLEAN_SHARED -> {
                val result = resultKey;
                SharedManager.getInstance(resign.activity().applicationContext).saveBoolean(call.argument<String>("key")!!, call.argument<Boolean>("value")!!)
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, it);
                        }, DebugUtil::printStackTrace).addTo(disposable)
            }
            SAVE_STRINGLIST_SHARED -> {
                val result = resultKey;
                val temp = call.argument<List<String>>("value")!!
                val set = HashSet<String>();
                set.addAll(temp)
                SharedManager.getInstance(resign.activity().applicationContext).saveStringList(call.argument<String>("key")!!, set)
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, it);
                        }, DebugUtil::printStackTrace).addTo(disposable)
            }
            GET_STRING_SHARED -> {
                val result = resultKey;
                SharedManager.getInstance(resign.activity().applicationContext).getString(call.argument<String>("key")!!, call.argument<String>("value"))
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, if (it == null) {
                                ""
                            } else {
                                it
                            });
                        }, {
                            DebugUtil.printStackTrace(it);
                            ResultManager.getInstance().resultError(result, it.message!!, it.message!!);
                        }).addTo(disposable)
            }
            GET_INT_SHARED -> {
                val result = resultKey;
                SharedManager.getInstance(resign.activity().applicationContext).getInt(call.argument<String>("key")!!, call.argument<Int>("value")!!)
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, it);
                        }, DebugUtil::printStackTrace).addTo(disposable)
            }
            GET_FLOAT_SHARED -> {
                val result = resultKey;
                SharedManager.getInstance(resign.activity().applicationContext).getFloat(call.argument<String>("key")!!, call.argument<Float>("value")!!)
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, it);
                        }, DebugUtil::printStackTrace).addTo(disposable)
            }
            GET_BOOLEAN_SHARED -> {
                val result = resultKey;
                SharedManager.getInstance(resign.activity().applicationContext).getBoolean(call.argument<String>("key")!!, call.argument<Boolean>("value")!!)
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, it);
                        }, DebugUtil::printStackTrace).addTo(disposable)
            }
            GET_STRINGLIST_SHARED -> {
                val result = resultKey;
                val temp = call.argument<List<String>>("value")
                val set = HashSet<String>()
                temp?.run {
                    set.addAll(this)
                }
                SharedManager.getInstance(resign.activity().applicationContext).getStringList(call.argument<String>("key")!!, set)
                        .subscribe({
                            ResultManager.getInstance().resultSuccess(result, it);
                        }, {
                            DebugUtil.printStackTrace(it);
                            ResultManager.getInstance().resultError(result, it.message!!, it.message!!);
                        }).addTo(disposable)
            }
            QUIT_PAGE -> {
                disposable.dispose()
                disposable = CompositeDisposable()
                ResultManager.getInstance().resultSuccess(resultKey, true)
            }
            else -> result.notImplemented()
        }
    }

    fun ScanImage(resultKey: Long) {

        ImageRespository.getInstance().scanPhoneImage(resign.context().applicationContext).subscribe(
                {
                    record = it
                    ResultManager.getInstance().resultSuccess(resultKey, it);
                    if (isTaskingExectured) {
                        return@subscribe;
                    }
                    isTaskingExectured = true
                    savePreview();
                }, {
            DebugUtil.printStackTrace(it);
            ResultManager.getInstance().resultError(resultKey, it.toString(), it);
        }).addTo(disposable);
    }

    fun savePreview() {
        ImageRespository.getInstance().savePreviewImg(resign.context().applicationContext, object : ImageRespository.savePreviewListener {
            override fun onSuccess(data: HashMap<String, ArrayList<HashMap<String, Any>>>) {
                Handler(resign.activeContext().applicationContext.mainLooper).post {
                    listener?.run {
                        this.success(data)
                    }
                }
            }
        });
    }

    @TargetApi(Build.VERSION_CODES.M)
    private fun checkPermission(listener: PermissionListener) {
        val activity = resign.activity()
        val writePremission = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        val readPremission = activity.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
        val cameraPremission = activity.checkSelfPermission(Manifest.permission.CAMERA);
        if (writePremission != PackageManager.PERMISSION_GRANTED ||
                cameraPremission != PackageManager.PERMISSION_GRANTED ||
                readPremission != PackageManager.PERMISSION_GRANTED) {
            if (activity.shouldShowRequestPermissionRationale(Manifest.permission
                            .WRITE_EXTERNAL_STORAGE)) {
                Toast.makeText(activity.applicationContext, "请开通相关权限，否则无法正常使用本应用！", Toast.LENGTH_SHORT).show()
            }
            if (activity.shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
                Toast.makeText(activity.applicationContext, "请开通相关权限，否则无法正常使用本应用", Toast.LENGTH_SHORT).show()
            }
            if (activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
                Toast.makeText(activity.applicationContext, "请开通相关权限，否则无法正常使用本应用", Toast.LENGTH_SHORT).show()
            }
            //申请权限
            activity.requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE
                    , Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE), PREMISSION);
        } else {
//            Toast.makeText(activity.applicationContext, "授权成功！", Toast.LENGTH_SHORT).show();
            listener.OK()
        }

        resign.addRequestPermissionsResultListener { id, permissions, grantResults ->
            if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
                    && grantResults[1] == PackageManager.PERMISSION_GRANTED
                    && grantResults[2] == PackageManager.PERMISSION_GRANTED) {
                listener.OK();
            } else {
                Toast.makeText(activity.applicationContext, "请同意权限", Toast.LENGTH_SHORT).show()
                result?.run {
                    this.error("没有权限！！", "no premission", "没有权限！！");
                }
            }
            true;
        }
        resign.addActivityResultListener { requestCode, resultCode, intent ->
            when (requestCode) {
                CAMERA_REQUEST_CODE -> {
                    if (resultCode == RESULT_OK) {
                        if (nativeImage == null) {
                            ResultManager.getInstance().resultSuccess(gotoNativeCameraKey, nativeImage!!.absolutePath);
                        } else {
                            ResultManager.getInstance().resultSuccess(gotoNativeCameraKey, "");
                        }
//                        nativeImage?.run {
//                        }
//                        result?.run {
//                            if (nativeImage != null) {
//                                this.success(nativeImage!!.absolutePath);
//                            } else {
//                                this.success("");
//                            }
//                        }
                    } else {
                        ResultManager.getInstance().resultSuccess(gotoNativeCameraKey, "");
//                        result?.run {
//                            this.success("")
//                        }
                    }
                }
            }
            true
        };
        isAdded = true;
    }

    interface PermissionListener {
        fun OK()
    }
}


