package com.casic.common.detector.gd.view

import android.app.DatePickerDialog
import android.content.ComponentName
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.ServiceConnection
import android.hardware.Camera
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
import android.os.IBinder
import android.util.Log
import android.view.View
import android.widget.AdapterView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.adapter.EditableImageAdapter
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.callback.OnImageCompressListener
import com.casic.common.detector.gd.callback.OnSerialPortListener
import com.casic.common.detector.gd.databinding.ActivityInstallMarkerBinding
import com.casic.common.detector.gd.extensions.compressImage
import com.casic.common.detector.gd.extensions.getDefaultValue
import com.casic.common.detector.gd.extensions.hexToString
import com.casic.common.detector.gd.extensions.initImmersionBar
import com.casic.common.detector.gd.extensions.isNumber
import com.casic.common.detector.gd.extensions.setDefaultValue
import com.casic.common.detector.gd.extensions.show
import com.casic.common.detector.gd.extensions.toColor
import com.casic.common.detector.gd.extensions.toHex
import com.casic.common.detector.gd.extensions.toObjectType
import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationTool
import com.casic.common.detector.gd.vm.TaskViewModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.appendZero
import com.pengxh.kt.lite.extensions.dateToTimestamp
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.extensions.timestampToCompleteDate
import com.pengxh.kt.lite.extensions.timestampToTime
import com.pengxh.kt.lite.extensions.toJson
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.widget.TitleBarView
import java.io.File
import java.util.Calendar
import java.util.Date

class InstallMarkerActivity : KotlinBaseActivity<ActivityInstallMarkerBinding>(),
    OnSerialPortListener {

    private val kTag = "InstallMarkerActivity"
    private val context = this
    private val calendar by lazy { Calendar.getInstance() }
    private val locationTool by lazy { LocationTool(this) }
    private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] }
    private val realPaths = ArrayList<String>() //真实图片路径
    private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM)
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()
    private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build()
    private var soundResourceId = 0
    private var serialPortService: SerialPortService? = null
    private lateinit var imageAdapter: EditableImageAdapter

    override fun initEvent() {
        //返回
        binding.titleView.setOnClickListener(object : TitleBarView.OnClickListener {
            override fun onLeftClick() {
                finish()
            }

            override fun onRightClick() {

            }
        })

        binding.objectInclude.objectTypeSpinner.onItemSelectedListener =
            object : AdapterView.OnItemSelectedListener {
                override fun onItemSelected(
                    parent: AdapterView<*>?, view: View?, position: Int, id: Long
                ) {
                    when (position) {
                        0 -> {
                            //显示管线属性
                            binding.objectInclude.pipeInclude.root.visibility = View.VISIBLE
                            binding.objectInclude.pipeAttachInclude.root.visibility = View.GONE
                            binding.objectInclude.pipeFeatureInclude.root.visibility = View.GONE
                            binding.objectInclude.pipeCrossInclude.root.visibility = View.GONE
                        }

                        1 -> {
                            //显示管线附属物属性
                            binding.objectInclude.pipeInclude.root.visibility = View.GONE
                            binding.objectInclude.pipeAttachInclude.root.visibility = View.VISIBLE
                            binding.objectInclude.pipeFeatureInclude.root.visibility = View.GONE
                            binding.objectInclude.pipeCrossInclude.root.visibility = View.GONE
                        }

                        2 -> {
                            //显示管线特征点属性
                            binding.objectInclude.pipeInclude.root.visibility = View.GONE
                            binding.objectInclude.pipeAttachInclude.root.visibility = View.GONE
                            binding.objectInclude.pipeFeatureInclude.root.visibility = View.VISIBLE
                            binding.objectInclude.pipeCrossInclude.root.visibility = View.GONE
                        }

                        3 -> {
                            //显示交叉穿越点属性
                            binding.objectInclude.pipeInclude.root.visibility = View.GONE
                            binding.objectInclude.pipeAttachInclude.root.visibility = View.GONE
                            binding.objectInclude.pipeFeatureInclude.root.visibility = View.GONE
                            binding.objectInclude.pipeCrossInclude.root.visibility = View.VISIBLE
                        }
                    }
                }

                override fun onNothingSelected(parent: AdapterView<*>?) {

                }
            }

        //安装
        binding.installButton.setOnClickListener {
            val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") as String
            val objectId = SaveKeyValues.getValue(LocaleConstant.OBJECT_ID, "") as String
            if (binding.objectInclude.pipeInclude.markerObjectTypeView.text.isNullOrBlank()) {
                when (binding.objectInclude.objectTypeSpinner.selectedItem.toString()) {
                    "管线" -> "请输入管线种类！".show(this)
                    "管线附属物" -> "请输入附属物名称！".show(this)
                    "管线特征管点" -> "请输入特征管点！".show(this)
                    "交叉穿越点" -> "请输入上层管种类！".show(this)
                }
                return@setOnClickListener
            }

            if (binding.objectInclude.objectTypeSpinner.selectedItem == "管线") {
                if (binding.objectInclude.pipeInclude.pipelineDiameterView.text.isNullOrBlank()) {
                    "请输入管径".show(this)
                    return@setOnClickListener
                }

                if (binding.objectInclude.pipeInclude.buryDeepView.text.isNullOrBlank()) {
                    "请输入埋深".show(this)
                    return@setOnClickListener
                }
            }

            if (binding.objectInclude.objectTypeSpinner.selectedItem == "交叉穿越点") {
                if (binding.objectInclude.pipeCrossInclude.bottomPipeDiameterView.text.isNullOrBlank()) {
                    "请输入下层管管径".show(this)
                    return@setOnClickListener
                }
            }

            if (binding.objectInclude.areaView.text.isNullOrBlank()) {
                "请输入所属区域".show(this)
                return@setOnClickListener
            }

            if (binding.objectInclude.lineView.text.isNullOrBlank()) {
                "请输入所属线路".show(this)
                return@setOnClickListener
            }

            if (binding.objectInclude.roadView.text.isNullOrBlank()) {
                "请输入所属道路".show(this)
                return@setOnClickListener
            }

            if (binding.objectInclude.constructDateView.text.isNullOrBlank()) {
                "请选择建设年代".show(this)
                return@setOnClickListener
            }

            if (binding.objectInclude.ownerView.text.isNullOrBlank()) {
                "请输入权属单位".show(this)
                return@setOnClickListener
            }

            if (binding.identifierInclude.identifierIdView.text.isNullOrBlank()) {
                "请先读取标识器获取ID".show(this)
                return@setOnClickListener
            }

            if (binding.identifierInclude.identifierDeepView.text.isNullOrBlank()) {
                "请输入标识器埋深".show(this)
                return@setOnClickListener
            }

            if (binding.identifierInclude.personDeptView.text.isNullOrBlank()) {
                "请输入标识器安装部门".show(this)
                return@setOnClickListener
            }

            //先存本地再上传服务器
            saveMarkerInLocal()

            taskViewModel.installLabel(
                this, companyId,
                binding.objectInclude.objectTypeSpinner.selectedItem.toString().toObjectType(),
                binding.objectInclude.pipeInclude.markerObjectTypeView.text.toString(),
                binding.objectInclude.pipeInclude.materialSpinner.selectedItem.toString(),
                "${binding.objectInclude.pipeInclude.pipelineDiameterView.text}mm",
                "${binding.objectInclude.pipeInclude.buryDeepView.text}mm",
                binding.objectInclude.pipeCrossInclude.bottomPipeTypeSpinner.selectedItem.toString(),
                binding.objectInclude.pipeCrossInclude.bottomPipeMaterialSpinner.selectedItem.toString(),
                "${binding.objectInclude.pipeCrossInclude.bottomPipeDiameterView.text}mm",
                "${binding.objectInclude.pipeCrossInclude.bottomPointDeepView.text}mm",
                binding.objectInclude.pipeInclude.buryTypeSpinner.selectedItem.toString(),
                binding.objectInclude.areaView.text.toString(),
                binding.objectInclude.lineView.text.toString(),
                binding.objectInclude.roadView.text.toString(),
                binding.objectInclude.constructDateView.text.toString(),
                binding.objectInclude.ownerView.text.toString(),
                objectId,
                binding.identifierInclude.identifierIdView.text.toString(),
                binding.identifierInclude.identifierTypeSpinner.selectedItem.toString(),
                "${binding.identifierInclude.identifierDeepView.text}mm",
                binding.identifierInclude.personDeptView.text.toString(),
                binding.identifierInclude.installTimeView.text.toString(),
                binding.identifierInclude.lngView.text.toString(),
                binding.identifierInclude.latView.text.toString(),
                binding.identifierInclude.colorSpinner.selectedItem.toString().toColor(),
                binding.remarkView.text.toString(),
                realPaths
            )

            //保存默认值
            "markerObjectTypeView".setDefaultValue(binding.objectInclude.pipeInclude.markerObjectTypeView.text.toString())
            "pipelineDiameterView".setDefaultValue(binding.objectInclude.pipeInclude.pipelineDiameterView.text.toString())
            "buryDeepView".setDefaultValue(binding.objectInclude.pipeInclude.buryDeepView.text.toString())
            "bottomPipeDiameterView".setDefaultValue(binding.objectInclude.pipeCrossInclude.bottomPipeDiameterView.text.toString())
            "bottomPointDeepView".setDefaultValue(binding.objectInclude.pipeCrossInclude.bottomPointDeepView.text.toString())
            "areaView".setDefaultValue(binding.objectInclude.areaView.text.toString())
            "lineView".setDefaultValue(binding.objectInclude.lineView.text.toString())
            "roadView".setDefaultValue(binding.objectInclude.roadView.text.toString())
            "ownerView".setDefaultValue(binding.objectInclude.ownerView.text.toString())
            "identifierDeepView".setDefaultValue(binding.identifierInclude.identifierDeepView.text.toString())
            "personDeptView".setDefaultValue(binding.identifierInclude.personDeptView.text.toString())
        }

        //读标识器
        binding.readMarkerButton.setOnClickListener {
            LoadingDialog.show(this, "标识器读取中，请稍后...")
            countDownTimer.start()
            binding.readMarkerButton.isEnabled = false
            serialPortService?.openSerialPort(arrayListOf('2'), this)
        }
    }


    override fun onDataReceived(buffer: ByteArray) {
        val hex = buffer.toHex()
        Log.d(kTag, hex)
        val markerId = hex.take(20).hexToString()
        if (markerId.isNumber()) {
            runOnUiThread {
                LoadingDialog.dismiss()
                countDownTimer.cancel()
                serialPortService?.closeSerialPort()
                binding.readMarkerButton.isEnabled = true
                binding.identifierInclude.identifierIdView.text = markerId
            }
        }
    }

    /**
     * 搜索标识器超时倒计时
     * */
    private val countDownTimer = object : CountDownTimer(10 * 1000, 500) {
        override fun onTick(millisUntilFinished: Long) {
            soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f)
        }

        override fun onFinish() {
            LoadingDialog.dismiss()
            "读取此标识器ID超时，请重试".show(context)
            binding.readMarkerButton.isEnabled = true
            serialPortService?.closeSerialPort()
        }
    }

    private fun saveMarkerInLocal() {
        val objectId = SaveKeyValues.getValue(LocaleConstant.OBJECT_ID, "") as String

        val marker = MarkerLocalBean()
        marker.objectType = binding.objectInclude.objectTypeSpinner.selectedItem.toString()
        marker.pipelineType = binding.objectInclude.pipeInclude.markerObjectTypeView.text.toString()
        marker.pipelineMaterial =
            binding.objectInclude.pipeInclude.materialSpinner.selectedItem.toString()
        marker.pipelineDiameter = "${binding.objectInclude.pipeInclude.pipelineDiameterView.text}mm"
        marker.buryDepth = "${binding.objectInclude.pipeInclude.buryDeepView.text}mm"
        marker.underlyingPipelineType =
            binding.objectInclude.pipeCrossInclude.bottomPipeTypeSpinner.selectedItem.toString()
        marker.underlyingPipelineMaterial =
            binding.objectInclude.pipeCrossInclude.bottomPipeMaterialSpinner.selectedItem.toString()
        marker.underlyingPipelineDiameter =
            "${binding.objectInclude.pipeCrossInclude.bottomPipeDiameterView.text}mm"
        marker.underlyingPipelineDepth =
            "${binding.objectInclude.pipeCrossInclude.bottomPointDeepView.text}mm"
        marker.buryMethod =
            binding.objectInclude.pipeInclude.buryTypeSpinner.selectedItem.toString()
        marker.area = binding.objectInclude.areaView.text.toString()
        marker.line = binding.objectInclude.lineView.text.toString()
        marker.road = binding.objectInclude.roadView.text.toString()
        marker.constructTime = binding.objectInclude.constructDateView.text.toString()
        marker.owner = binding.objectInclude.ownerView.text.toString()
        marker.objectId = objectId
        marker.markerId = binding.identifierInclude.identifierIdView.text.toString()
        marker.markerType = binding.identifierInclude.identifierTypeSpinner.selectedItem.toString()
        marker.markerDepth = "${binding.identifierInclude.identifierDeepView.text}mm"
        marker.installationDept = binding.identifierInclude.personDeptView.text.toString()
        marker.updateTime = binding.identifierInclude.installTimeView.text.toString()
        marker.lng = binding.identifierInclude.lngView.text.toString()
        marker.lat = binding.identifierInclude.latView.text.toString()
        marker.color = binding.identifierInclude.colorSpinner.selectedItem.toString().toColor()
        marker.remark = binding.remarkView.text.toString()
        marker.imagePath = realPaths.toJson()

        DataBaseManager.get.saveMarkerInLocale(marker)
    }

    private fun takePicture() {
        PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
            .forResult(object : OnResultCallbackListener<LocalMedia> {
                override fun onResult(result: ArrayList<LocalMedia>?) {
                    if (result == null) {
                        "拍照失败，请重试".show(context)
                        return
                    }
                    analyticalSelectResults(result[0])
                }

                override fun onCancel() {

                }
            })
    }

    private fun analyticalSelectResults(result: LocalMedia) {
        //压缩图片
        result.realPath.compressImage(context, object : OnImageCompressListener {
            override fun onSuccess(file: File) {
                realPaths.add(file.absolutePath)
                imageAdapter.setupImage(realPaths)
            }

            override fun onError(e: Throwable) {
                e.printStackTrace()
            }
        })
    }

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
            if (iBinder is SerialPortService.ServiceBinder) {
                serialPortService = iBinder.getSerialPortService()
                Log.d(kTag, "onServiceConnected: 服务已绑定")
            }
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            //在连接正常关闭的情况下不会被调用, 只在Service被破坏了或者被杀死的时候调用
        }
    }

    override fun initOnCreate(savedInstanceState: Bundle?) {
        //绑定串口通信服务
        Intent(this, SerialPortService::class.java).also {
            bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
        }

        locationTool.getCurrentLocation(true, object : OnGetLocationListener {
            override fun onSuccess(location: AMapLocation) {
                binding.identifierInclude.lngView.text = location.longitude.toString()
                binding.identifierInclude.latView.text = location.latitude.toString()
            }

            override fun onError() {
                "当前位置信号差，无法获取定位".show(context)
            }
        })
        soundResourceId = soundPool.load(this, R.raw.ring3, 1)

        //初始化数据
        initDefaultData()
    }

    override fun initViewBinding(): ActivityInstallMarkerBinding {
        return ActivityInstallMarkerBinding.inflate(layoutInflater)
    }

    override fun observeRequestState() {
        taskViewModel.loadState.observe(this) {
            when (it) {
                LoadState.Loading -> LoadingDialog.show(this, "标识器安装中，请稍后...")

                LoadState.Success -> {
                    LoadingDialog.dismiss()
                    clearDefaultData()
                    "安装成功".show(this)
                }

                else -> LoadingDialog.dismiss()
            }
        }
    }

    override fun setupTopBarLayout() {
        binding.rootView.initImmersionBar(this, true, R.color.mainBackground)
    }

    private fun initDefaultData() {
        imageAdapter = EditableImageAdapter(this, 3, 3)
        binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter

        //设置默认值
        binding.objectInclude.pipeInclude.markerObjectTypeView.setText("markerObjectTypeView".getDefaultValue())
        binding.objectInclude.pipeInclude.pipelineDiameterView.setText("pipelineDiameterView".getDefaultValue())
        binding.objectInclude.pipeInclude.buryDeepView.setText("buryDeepView".getDefaultValue())
        binding.objectInclude.pipeCrossInclude.bottomPipeDiameterView.setText("bottomPipeDiameterView".getDefaultValue())
        binding.objectInclude.pipeCrossInclude.bottomPointDeepView.setText("bottomPointDeepView".getDefaultValue())
        binding.objectInclude.areaView.setText("areaView".getDefaultValue())
        binding.objectInclude.lineView.setText("lineView".getDefaultValue())
        binding.objectInclude.roadView.setText("roadView".getDefaultValue())
        binding.objectInclude.ownerView.setText("ownerView".getDefaultValue())
        binding.identifierInclude.identifierDeepView.setText("identifierDeepView".getDefaultValue())
        binding.identifierInclude.personDeptView.setText("personDeptView".getDefaultValue())

        /**************************************************************************************/
        binding.objectInclude.objectTypeSpinner.show(this, LocaleConstant.POINT_TYPE_ARRAY, 0)
        binding.objectInclude.pipeInclude.materialSpinner.show(
            this, LocaleConstant.PIPE_MATERIAL_ARRAY, 0
        )
        binding.objectInclude.pipeAttachInclude.attachSpinner.show(
            this, LocaleConstant.ATTACH_NAME_ARRAY, 0
        )
        binding.objectInclude.pipeFeatureInclude.featureSpinner.show(
            this, LocaleConstant.FEATURE_NAME_ARRAY, 0
        )
        binding.objectInclude.pipeCrossInclude.topPipeTypeSpinner.show(
            this, LocaleConstant.PIPE_TYPE_ARRAY, 0
        )
        binding.objectInclude.pipeCrossInclude.topPipeMaterialSpinner.show(
            this, LocaleConstant.PIPE_MATERIAL_ARRAY, 0
        )
        binding.objectInclude.pipeCrossInclude.bottomPipeTypeSpinner.show(
            this, LocaleConstant.PIPE_TYPE_ARRAY, 0
        )
        binding.objectInclude.pipeCrossInclude.bottomPipeMaterialSpinner.show(
            this, LocaleConstant.PIPE_MATERIAL_ARRAY, 0
        )
        binding.objectInclude.pipeInclude.buryTypeSpinner.show(
            this, LocaleConstant.BURY_METHOD_ARRAY, 0
        )
        binding.objectInclude.constructDateView.setOnClickListener {
            val datePicker = DatePickerDialog(
                this, null,
                calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH)
            )
            datePicker.show()

            datePicker.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
                val year = datePicker.datePicker.year
                val month = datePicker.datePicker.month + 1
                val day = datePicker.datePicker.dayOfMonth
                val selectedDate = String.format(
                    "%s-%s-%s", year, month.appendZero(), day.appendZero()
                )

                //当前时间
                val current = System.currentTimeMillis().timestampToTime()
                val today = "$selectedDate $current".dateToTimestamp()
                if (Date(today).after(Date())) {
                    "建设年代不能早于当前日期".show(context)
                } else {
                    datePicker.dismiss()
                    binding.objectInclude.constructDateView.text = selectedDate
                }
            }
        }
        binding.identifierInclude.identifierTypeSpinner.show(
            this, LocaleConstant.IDENTIFIER_TYPE_ARRAY, 0
        )
        binding.identifierInclude.installTimeView.text =
            System.currentTimeMillis().timestampToCompleteDate()
        binding.identifierInclude.colorSpinner.show(this, LocaleConstant.COLOR_ARRAY, 0)

        imageAdapter.setOnItemClickListener(object : EditableImageAdapter.OnItemClickListener {
            override fun onAddImageClick() {
                if (Camera.getNumberOfCameras() == 0) {
                    "未检测到相机模块，无法拍照".show(context)
                    return
                }
                takePicture()
            }

            override fun onItemClick(position: Int) {
                if (realPaths[position].isEmpty()) {
                    "图片加载失败，无法查看大图".show(context)
                } else {
                    navigatePageTo<BigImageActivity>(position, realPaths)
                }
            }

            override fun onItemLongClick(view: View?, position: Int) {
                imageAdapter.deleteImage(position)
            }
        })
    }

    //清除默认数据
    private fun clearDefaultData() {
        "markerObjectTypeView".setDefaultValue("")
        "pipelineDiameterView".setDefaultValue("")
        "buryDeepView".setDefaultValue("")
        "bottomPipeDiameterView".setDefaultValue("")
        "bottomPointDeepView".setDefaultValue("")
        "areaView".setDefaultValue("")
        "lineView".setDefaultValue("")
        "roadView".setDefaultValue("")
        "ownerView".setDefaultValue("")
        "identifierDeepView".setDefaultValue("")
        "personDeptView".setDefaultValue("")
    }

    override fun onDestroy() {
        super.onDestroy()
        locationTool.stopLocation()
        unbindService(serviceConnection)
    }
}