package com.lovense.sdkdemo

import android.annotation.SuppressLint
import android.content.DialogInterface
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.component.toymodule.command.control.bean.CommandType
import com.component.toymodule.command.control.bean.LushLightColorType
import com.lovense.sdkdemo.databinding.ActivityToyBinding
import com.lovense.sdklibrary.Lovense
import com.lovense.sdklibrary.LovenseToy
import com.lovense.sdklibrary.callBack.LovenseError
import com.lovense.sdklibrary.callBack.OnCallBackAidLightStatusListener
import com.lovense.sdklibrary.callBack.OnCallBackBatteryV2Listener
import com.lovense.sdklibrary.callBack.OnCallBackDeviceTypListener
import com.lovense.sdklibrary.callBack.OnCallBackGetAutoSwitchListener
import com.lovense.sdklibrary.callBack.OnCallBackLightStatusListener
import com.lovense.sdklibrary.callBack.OnCallBackMission2Listener
import com.lovense.sdklibrary.callBack.OnCallBackMoveListener
import com.lovense.sdklibrary.callBack.OnCallBackSolaceProListener
import com.lovense.sdklibrary.callBack.OnCommandErrorListener
import com.lovense.sdklibrary.callBack.OnCommandSuccessListener
import com.lovense.sdklibrary.callBack.OnConnectListener
import com.lovense.sdklibrary.callBack.OnLightColorListener
import com.lovense.sdklibrary.callBack.OnSendCommandErrorListener
import org.greenrobot.eventbus.EventBus

/**
 * Created  on 2019/5/14 09:17
 *
 * @author zyy
 */
open class ToyActivity : AppCompatActivity(), OnSeekBarChangeListener {
    private lateinit var toyId: String
    private lateinit var connectListener: OnConnectListener
    private lateinit var binding: ActivityToyBinding

    private var isAutoStop = 1                  // AutoSwitch: autoStop 1: on  0: off
    private var isReconnectToLastLevel = 1      // AutoSwitch: reconnectToLastLevel 1: on  0: off

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityToyBinding.inflate(layoutInflater)
        setContentView(binding.root)

        initUI()
        initToyConnectStatus()
        initSendCmdListener()
    }

    override fun onDestroy() {
        super.onDestroy()
        Lovense.getInstance(application).disconnect(toyId)
    }

    protected fun initUI() {
        val intent = intent
        toyId = intent.getStringExtra("toyId") ?: ""

        binding.back.setOnClickListener { finish() }
        binding.stopConnect.setOnClickListener {
            if (Lovense.getInstance(application).isConnected(toyId)) {
                Lovense.getInstance(application).disconnect(toyId)
                EventBus.getDefault().post(ToyConnectEvent(-1, toyId))
                binding.stopConnect.text = "connect"
            } else {
                Lovense.getInstance(application).connectToy(toyId)
            }
        }

        binding.tvGetBattery.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_BATTERY)
        }

        binding.tvAlightOff.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.ALIGHT_OFF)
        }
        binding.tvAlightOn.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.ALIGHT_ON)
        }
        binding.tvGetAlight.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_ALIGHT_STATUS)
        }

        binding.tvLightOff.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.LIGHT_OFF)
        }
        binding.tvLightOn.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.LIGHT_ON)
        }
        binding.tvGetLight.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_LIGHT_STATUS)
        }

        binding.tvTurnOffAutoSwitch.setOnClickListener {
            isAutoStop = 0
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_AUTO_SWITCH, intArrayOf(isAutoStop, isReconnectToLastLevel))
        }
        binding.tvTurnOnAutoSwitch.setOnClickListener {
            isAutoStop = 1
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_AUTO_SWITCH, intArrayOf(isAutoStop, isReconnectToLastLevel))
        }
        binding.tvTurnOffReconnectToLastLevel.setOnClickListener {
            isReconnectToLastLevel = 0
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_AUTO_SWITCH, intArrayOf(isAutoStop, isReconnectToLastLevel))
        }
        binding.tvTurnOnReconnectToLastLevel.setOnClickListener {
            isReconnectToLastLevel = 1
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_AUTO_SWITCH, intArrayOf(isAutoStop, isReconnectToLastLevel))
        }
        binding.tvGetAutoSwitch.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_AUTO_SWITCH)
        }
        binding.tvGetToyCommands.setOnClickListener {
            val cmdString = Lovense.getInstance(application).getSupportedCommands(toyId)?.map {
                it.name
            }?.joinToString(",  ") ?: "Connot get commands"
            AlertDialog.Builder(this@ToyActivity).setTitle("Toy Support Commands").setMessage(cmdString).setNeutralButton("Close", {dialog, whick ->

            }).show()
        }

        binding.tvStartMoveWaggle.setOnClickListener {
            binding.tvMovement.text = "Speed:0"
            Lovense.getInstance(application).sendCommand(toyId, CommandType.START_MOVE)
        }
        binding.tvStopMoveWaggle.setOnClickListener {
            binding.tvMovement.text = ""
            Lovense.getInstance(application).sendCommand(toyId, CommandType.STOP_MOVE)
        }

        binding.tvFlash.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.FLASH)
        }

        binding.btnMission2GetMode.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_TOUCH_MODE)
        }
        binding.btnMission2SetMode0.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_TOUCH_MODE, 0)
        }
        binding.btnMission2SetMode1.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_TOUCH_MODE, 1)
        }
        binding.btnMission2SetMode2.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_TOUCH_MODE, 2)
        }
        binding.btnMission2SetMode3.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_TOUCH_MODE, 3)
        }
        binding.btnMission2SetMode5.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_TOUCH_MODE, 5)
        }
        binding.btnMission2GetTouchLevel.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_TOUCH_LEVEL)
        }
        binding.btnMission2GetTouchValue.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_TOUCH_VALUE)
        }
        binding.btnMission2SetTouchValue.setOnClickListener {
            val index = binding.etMission2SetTouchValueIndex.text.toString().toIntOrNull()
            val value = binding.etMission2SetTouchValue.text.toString().toIntOrNull()
            if (index == null || value == null) {
                showToast("The params is empty!")
                return@setOnClickListener
            }
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_TOUCH_VALUE, intArrayOf(index, value))
        }
        binding.btnMission2SetTouchLevel.setOnClickListener {
            val level = binding.etMission2SetTouchLevel.text.toString().toIntOrNull()
            if (level == null) {
                showToast("The param is empty!")
                return@setOnClickListener
            }
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_TOUCH_LEVEL, level)
        }
        binding.commVibrate.setOnSeekBarChangeListener(this)
        binding.presetLevel.setOnSeekBarChangeListener(this)
        binding.noraRotate.setOnSeekBarChangeListener(this)
        binding.noraRotateTrue.setOnSeekBarChangeListener(this)
        binding.noraRotateFalse.setOnSeekBarChangeListener(this)
        binding.tvRotateChange.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.ROTATE_CHANGE)
        }

        binding.maxAirIn.setOnSeekBarChangeListener(this)
        binding.maxAirOut.setOnSeekBarChangeListener(this)
        binding.maxAirLoop.setOnSeekBarChangeListener(this)

        binding.edgeVibrate1.setOnSeekBarChangeListener(this)
        binding.edgeVibrate2.setOnSeekBarChangeListener(this)

        binding.flexerVibrate.setOnSeekBarChangeListener(this)
        binding.flexerFinger.setOnSeekBarChangeListener(this)

        binding.thrust.setOnSeekBarChangeListener(this)
        binding.lapisVibrate1.setOnSeekBarChangeListener(this)
        binding.lapisVibrate2.setOnSeekBarChangeListener(this)
        binding.lapisVibrate3.setOnSeekBarChangeListener(this)
        binding.sendLapisVibrate.setOnClickListener {
            val v1 = binding.etLapisVibrate1.text.toString().toIntOrNull() ?: -1
            val v2 = binding.etLapisVibrate2.text.toString().toIntOrNull() ?: -1
            val v3 = binding.etLapisVibrate3.text.toString().toIntOrNull() ?: -1
            Lovense.getInstance(application).sendCommand(toyId, CommandType.MULTIPLY, intArrayOf(v1, v2, v3))
        }

        binding.solaceThrust.setOnSeekBarChangeListener(this)
        binding.solaceDepth.setOnSeekBarChangeListener(this)

        // solacePro
        binding.btnSolaceproGetSite.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_SITE)
        }
        binding.btnSolaceproSetSite.setOnClickListener {
            val value = binding.etSolaceproSetSiteValue.text.toString().toIntOrNull()
            if (value != null) {
                Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_SITE, value)
            } else {
                showToast("The params of setSite is empty!")
                return@setOnClickListener
            }
        }
        binding.btnSolaceproStartFb.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.START_FEEDBACK)
        }
        binding.btnSolaceproStopFb.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.STOP_FEEDBACK)
        }
        binding.btnSolaceproSpeed.setOnClickListener {
            val level = binding.etSolaceproSpeedValue.text.toString().toIntOrNull()
            val minPos = binding.etSolaceproStartPos.text.toString().toIntOrNull()
            val maxPos = binding.etSolaceproEndPos.text.toString().toIntOrNull()
            if (level == null || minPos == null || maxPos == null) {
                showToast("The three params must not be empty !")
                return@setOnClickListener
            }
            Lovense.getInstance(application).sendCommand(toyId, CommandType.SPEED, intArrayOf(level, minPos, maxPos))
        }

        // Gush2
        binding.sbGush2Oscillate.setOnSeekBarChangeListener(this)

        // Osci3
        binding.sbOsci3Vibrate.setOnSeekBarChangeListener(this)
        binding.sbOsci3Oscillate.setOnSeekBarChangeListener(this)
        binding.btnOsci3Multi.setOnClickListener {
            val vibrate = binding.etOsci3Vibrate.text.toString().toIntOrNull()
            val oscillate = binding.etOsci3Oscillate.text.toString().toIntOrNull()
            if (vibrate == null || oscillate == null) {
                showToast("The two params must not be empty!")
                return@setOnClickListener
            }
            Lovense.getInstance(application).sendCommand(toyId, CommandType.MULTIPLY, intArrayOf(vibrate, oscillate))
        }

        // Lush4
        binding.btnLush4GetLightColor.setOnClickListener {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_LIGHT_COLOR)
        }
        binding.sbLush4SetLightColor.setOnSeekBarChangeListener(this)

    }

    private fun initToyConnectStatus() {
        updateStopConnectUI()
        // toy isConnected
        if (Lovense.getInstance(application).isConnected(toyId)) {
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_DEVICE_TYPE)
            Lovense.getInstance(application).sendCommand(toyId, CommandType.GET_BATTERY)
        }

        // set connectListener
        connectListener = object : OnConnectListener {
            override fun onConnect(toyId: String, status: String) {
                when (status) {
                    LovenseToy.STATE_CONNECTING -> {}
                    LovenseToy.STATE_CONNECTED -> {
                        binding.stopConnect.text = "Disconnect"
                        EventBus.getDefault().post(ToyConnectEvent(1, toyId))
                    }
                    LovenseToy.STATE_FAILED -> {
                        EventBus.getDefault().post(ToyConnectEvent(-1, toyId))
                    }
                }
            }

            override fun onError(error: LovenseError) {
                val msg = error.message
                showToast(msg)
                val btnName = if (error.code == 29) {
                    binding.stopConnect.text = "connect"
                    "CONNECT"
                } else {
                    "AGAIN"
                }
                AlertDialog.Builder(this@ToyActivity).apply {
                    setTitle("notice")
                    setMessage(msg)
                }.setPositiveButton("back") { dialog: DialogInterface, which: Int ->
                    dialog.dismiss()
                    finish()
                }.setNegativeButton(btnName) { dialog: DialogInterface, which: Int ->
                    Lovense.getInstance(application).connectToy(toyId)
                    dialog.dismiss()
                }.show()
            }
        }
        Lovense.getInstance(application).connectToy(toyId, connectListener)
    }

    override fun onResume() {
        super.onResume()
        updateStopConnectUI()
    }

    /**
     * update stopConnect tv UI
     */
    private fun updateStopConnectUI() {
        if (Lovense.getInstance(application).isConnected(toyId)) {
            binding.stopConnect.text = "Disconnect"
        } else  {
            binding.stopConnect.text = "connect"
        }
    }

    /** init cmd listener  */
    @SuppressLint("SetTextI18n")
    private fun initSendCmdListener() {
        Lovense.getInstance(application).addListener(toyId, OnSendCommandErrorListener { toyId, error ->
            showToast(error.message)
        })
        Lovense.getInstance(application).addListener(toyId, OnCallBackDeviceTypListener { toyId, toy ->
            binding.tvType.text = "Device Info：" + toy.type
            binding.tvAddress.text = "MAC Address：" + toy.macAddress
            binding.tvVersion.text = "Version：" + toy.version
            binding.tvName.text = "Toy Name：" + toy.name
            binding.tvToyVersion.text = "Toy Version：" + toy.getToyVersion()
            if (!TextUtils.isEmpty(toy.fullName)) {
                binding.tvFullName.visibility = View.VISIBLE
                binding.tvFullName.text = "Full Name：" + toy.fullName
            }
        })
//        Lovense.getInstance(application).addListener(toyId, OnCallBackBatteryListener { toyId, battery ->
//            binding.tvBattery.text = "Battery：$battery%"
//            Log.e("test", "OnCallBackBatteryListener battery: $battery")
//        })
        Lovense.getInstance(application).addListener(toyId, OnCallBackBatteryV2Listener { toyId, battery, isWork ->
            if (isWork) {
                binding.tvBattery.text = "Battery：$battery isWork: $isWork"
            } else {
                binding.tvBattery.text = "Battery：$battery isWork: $isWork"
            }
            Log.e("test", "OnCallBackBatteryV2Listener battery: $battery isWork: $isWork")
        })
        Lovense.getInstance(application).addListener(toyId, OnCallBackLightStatusListener { toyId, status ->
            showToast(if (status == 1) "Light on" else "Light off")
        })
        Lovense.getInstance(application).addListener(toyId, OnCallBackAidLightStatusListener { toyId, status ->
            showToast(if (status == 1) "AID Light on" else "AID Light off")
        })
        Lovense.getInstance(application).addListener(toyId, OnCallBackGetAutoSwitchListener { toyId, autoStop, reconnectToLastLevel ->
            isAutoStop = autoStop
            isReconnectToLastLevel = reconnectToLastLevel
            showToast("Auto Switch\nisAutoStop: $isAutoStop\nisReconnectToLastLevel: $isReconnectToLastLevel")
        })
        Lovense.getInstance(application).addListener(toyId, OnCallBackMoveListener { level ->
            binding.tvMovement.text = "Speed:$level"
        })
        Lovense.getInstance(application).addListener(toyId, OnCommandErrorListener { msg ->
            showToast(msg)
        })
        Lovense.getInstance(application).addListener(toyId, OnCommandSuccessListener { msg ->
            Log.e("test", "commandSuccess: $msg")
        })

        // mission2 sendCommand listener
        Lovense.getInstance(application).addListener(toyId, object : OnCallBackMission2Listener {
            override fun getTouchMode(mode: Int) {
                Log.e("test", "mission2 getTouchMode : $mode")
                binding.tvMission2Feedback.text = "result: $mode "
            }

            override fun touchModeFeedback(data: List<HashMap<String, Int>>) {
                // direction: 0入， 1出
                binding.tvMission2Feedback.text = ""
                for (item in data) {
                    // direction 0:enter ; 1:out
                    val result = "direction:" + item["direction"] + " speed:" + item["speed"] + " position: " + item["position"] + "\r\n"
                    Log.e("test", "mission2 touchMode3 or touchMode5, return data:$result")
                    binding.tvMission2Feedback.append(result)
                }
            }

            override fun getTouchLevel(value: Int) {
                binding.tvMission2Feedback.text = "Current usage level: $value"
            }

            override fun getTouchValue(value: Int, value2: Int, value3: Int) {
                binding.tvMission2Feedback.text = "All level-strength： $value ，$value2 ，$value3 "
            }
        })


        Lovense.getInstance(application).addListener(toyId, object : OnCallBackSolaceProListener {
            override fun getSite(direction: Int, position: Int) {
                Log.e("test", "SolacePro getSite direction: $direction ,position:$position")
                binding.tvSolaceproFeedback.text = "result direction: $direction ,position:$position "
            }

            override fun touchModeFeedback(data: List<HashMap<String, Int>>) {
                binding.tvSolaceproFeedback.text = ""
                for (item in data) {
                    val result = "direction:" + item["direction"] + " speed:" + item["speed"] + " position: " + item["position"] + "\r\n"
                    Log.e("test", "mission2 touchMode3 or touchMode5, return data:$result")
                    binding.tvSolaceproFeedback.append(result)
                }
            }
        })

        // Lush4 getColor listener
        Lovense.getInstance(application).addListener(toyId, OnLightColorListener { toyId, colorType ->
            binding.tvLush4GetColorResult.text = "colorType:${colorType?.name}"
        })
    }

    private fun showToast(message: String?) {
        if (message.isNullOrEmpty()) return
        runOnUiThread { Toast.makeText(this@ToyActivity, message, Toast.LENGTH_SHORT).show() }
    }

    override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
        when (seekBar.id) {
            R.id.comm_vibrate -> Lovense.getInstance(application).sendCommand(toyId, CommandType.VIBRATE, progress)

            R.id.preset_level -> Lovense.getInstance(application).sendCommand(toyId, CommandType.PRESET, progress)

            R.id.nora_rotate -> Lovense.getInstance(application).sendCommand(toyId, CommandType.ROTATE, progress)

            R.id.nora_rotate_true -> Lovense.getInstance(application).sendCommand(toyId, CommandType.ROTATE_CLOCKWISE, progress)

            R.id.nora_rotate_false -> Lovense.getInstance(application).sendCommand(toyId, CommandType.ROTATE_ANTI_CLOCKWISE, progress)

            R.id.max_air_in -> Lovense.getInstance(application).sendCommand(toyId, CommandType.AIR_IN, progress)

            R.id.max_air_out -> Lovense.getInstance(application).sendCommand(toyId, CommandType.AIR_OUT, progress)

            R.id.max_air_loop -> Lovense.getInstance(application).sendCommand(toyId, CommandType.AIR_AUTO, progress)

            R.id.edge_vibrate1, R.id.lapis_vibrate_1 -> Lovense.getInstance(application).sendCommand(toyId, CommandType.VIBRATE1, progress)

            R.id.edge_vibrate2, R.id.lapis_vibrate_2 -> Lovense.getInstance(application).sendCommand(toyId, CommandType.VIBRATE2, progress)

            R.id.flexer_vibrate -> Lovense.getInstance(application).sendCommand(toyId, CommandType.FLEXER_VIBRATE, progress)

            R.id.flexer_finger -> Lovense.getInstance(application).sendCommand(toyId, CommandType.FLEXER_FINGER, progress)

            R.id.thrust -> Lovense.getInstance(application).sendCommand(toyId, CommandType.THRUST, progress)

            R.id.lapis_vibrate_3 -> Lovense.getInstance(application).sendCommand(toyId, CommandType.VIBRATE3, progress)

            R.id.solace_thrust -> {
                val depth = binding.solaceDepth.progress
                Lovense.getInstance(application).sendCommand(toyId, CommandType.SOLACE, intArrayOf(progress, depth))
            }

            R.id.solace_depth -> {
                val thrust = binding.solaceThrust.progress
                Lovense.getInstance(application).sendCommand(toyId, CommandType.SOLACE, intArrayOf(thrust, progress))
            }

            R.id.sb_osci3_vibrate -> Lovense.getInstance(application).sendCommand(toyId, CommandType.VIBRATE, progress)
            R.id.sb_osci3_oscillate -> Lovense.getInstance(application).sendCommand(toyId, CommandType.OSCILLATE, progress)
            R.id.sb_gush2_oscillate -> Lovense.getInstance(application).sendCommand(toyId, CommandType.OSCILLATE, progress)

            R.id.sb_lush4_setLightColor -> {
                val color = binding.sbLush4SetLightColor.progress
                val colorType = LushLightColorType.fromValue(color)?.name
                binding.tvLush4SetLightColor.text = "SetLightColor:${colorType}"
            }
        }
    }

    override fun onStartTrackingTouch(seekBar: SeekBar) {}
    override fun onStopTrackingTouch(seekBar: SeekBar) {
        when (seekBar.id) {
            R.id.sb_lush4_setLightColor -> {
                val color = binding.sbLush4SetLightColor.progress
                // developer send command of SET_LIGHT_COLOR, the color value is LushLightColorType.value
                Lovense.getInstance(application).sendCommand(toyId, CommandType.SET_LIGHT_COLOR, color)
            }
        }
    }
}
