package com.sw.dualscreen.viewmodel import android.content.Context import android.net.Uri import androidx.lifecycle.viewModelScope import com.arcsoft.face.ErrorInfo import com.sw.dualscreen.GlobalData import com.sw.dualscreen.GlobalKey import com.sw.dualscreen.model.request.UserNutritionParam import com.sw.dualscreen.model.response.DinnerTypeInfo import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.UserFaceModel import com.sw.dualscreen.model.response.UserNutritionData import com.sw.dualscreen.utils.SPUtil import com.sw.plate.App import com.sw.plate.utils.Base64 import com.sw.plate.utils.ToastUtils import com.sw.plate.utils.arcface.FaceApi import com.sw.plate.utils.arcface.facedb.entity.FaceEntity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber import kotlin.math.atan class UserViewModel : BaseViewModel() { private val faceApi: FaceApi = FaceApi() // 识别出的列表 private val _identifiedFoodInfoList = MutableStateFlow>(emptyList()) val identifiedFoodInfoList: StateFlow> = _identifiedFoodInfoList // 搜索出的食物列表 private val _searchFoodInfoList = MutableStateFlow>(emptyList()) val searchFoodInfoList: StateFlow> = _searchFoodInfoList // 就餐数据 private val _nutritionData = MutableStateFlow(null) val nutritionData: StateFlow = _nutritionData /** * 饭点类型 早餐/午餐/晚餐 */ private val _dinnerTypeInfo = MutableStateFlow(null) val dinnerTypeInfo: StateFlow = _dinnerTypeInfo /** * 人脸加载完成 */ private val _loadFaceResult = MutableStateFlow(false) val loadFaceResult: StateFlow = _loadFaceResult private val _identifiedFoodInfoList2 = MutableStateFlow>(emptyList()) val identifiedFoodInfoList2: StateFlow> = _identifiedFoodInfoList2 /** * 获取token */ fun getEquipmentToken(qrcodeId: String = GlobalData.deviceId) { Timber.d("getEquipmentToken") launchWithLoading { val response = repository.getEquipmentToken(qrcodeId) if (parseResponse(response)) { // 缓存token SPUtil.getInstance().put(GlobalKey.KEY_TOKEN, response.result) // 首次运行获取人脸数据 if (SPUtil.getInstance().get(GlobalKey.KEY_FIRST_RUN, false) != true) { getUserFaceCache(index = 0) } } } } /** * 获取人脸数据 */ fun getUserFaceCache(index: Int = 0) { Timber.d("getUserFaceCache index = $index") launch { _loadFaceResult.value = false val response = repository.getUserFaceCache(index) if (parseResponse(response)) { // 获取成功一次后缓存状态 SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true) withContext(Dispatchers.Default) { val list: List = response.result?.data ?: emptyList() val faceEntity = list.map { FaceEntity(it.userId, null, Base64.decode(it.faceFeatureString)) } faceApi.updateFaceData(index, faceEntity) } val nextPageIndex = response.result?.nextPageIndex ?: -1 if (nextPageIndex > 0) { getUserFaceCache(nextPageIndex) } else { _loadFaceResult.value = true } } } } /** * 激活人脸识别引擎 */ fun activeEngine() { Timber.d("activeEngine") faceApi.activeEngine( App.getContext(), GlobalData.appId, GlobalData.sdkKey, GlobalData.activeKey, object : FaceApi.ActiveCallback { override fun onSuccess(activeCode: Int) { Timber.d("activeEngine activeCode = $activeCode") viewModelScope.launch(Dispatchers.Main) { when (activeCode) { ErrorInfo.MOK -> { ToastUtils.showToast("激活引擎成功") } ErrorInfo.MERR_ASF_ALREADY_ACTIVATED -> { // ToastUtils.showToast("引擎已激活,无需再次激活") } else -> { ToastUtils.showToast("激活引擎失败($activeCode)") } } } } override fun onFail(e: Exception?) { viewModelScope.launch(Dispatchers.Main) { ToastUtils.showToast("激活引擎异常,${e?.message}") } } }) } fun getIdentifiedFoodList() { Timber.d("identifiedFoodList") launchWithLoading { val response = repository.getRestInfoFoodsByType(foodName = "") if (parseResponse(response)) { _identifiedFoodInfoList.value = response.result ?: emptyList() } } } fun cleanIdentifiedFoodInfoList() { Timber.d("cleanIdentifiedFoodInfoList") _identifiedFoodInfoList.value = emptyList() } /** * 搜索食物 */ fun searchByFoodName(foodName: String) { Timber.d("searchByFoodName foodName = $foodName") launchWithLoading { val response = repository.getRestInfoFoodsByType(foodName = foodName) if (parseResponse(response)) { _searchFoodInfoList.value = response.result ?: emptyList() } } } fun cleanSearchFoodInfoList() { Timber.d("cleanSearchFoodInfoList") _searchFoodInfoList.value = emptyList() } /** * 获取用户就餐数据 */ fun getUserNutritionData(userId: String, foodId: String) { Timber.d("getUserNutritionData userId = ${userId}, foodId = $foodId") _nutritionData.value = null launch { val response = repository.getUserNutritionData(userId = userId, foodId = foodId) if (parseResponse(response)) { _nutritionData.value = response.result } } } fun getDinnerType() { Timber.d("getDinnerType") _dinnerTypeInfo.value = null launch { val response = repository.getDinnerType() if (parseResponse(response)) { _dinnerTypeInfo.value = response.result } } } /** * 提交就餐数据 */ fun postUserNutritionData(param: List) { Timber.d("postUserNutritionData param = $param") launch { val response = repository.postUserNutritionData(param) if (parseResponse(response)) { } } } fun getFoodInfo(foodName: String, action:(List)-> Unit = {}) { Timber.d("getFoodInfo") launchWithLoading { val response = repository.getFoodInfo(foodName = foodName) if (parseResponse(response)) { val list = response.result ?: emptyList() _identifiedFoodInfoList2.value = list action(list) } } } fun postImageData( context: Context, foodId: String, foodName: String, foodVector: String, uri: Uri ) { Timber.d("postImageData") launchWithLoading { val response = repository.postImageData( context, foodId = foodId, foodName = foodName, foodVector = foodVector, uri = uri ) if (parseResponse(response)) { Timber.tag("mzf").d("code=${response.code}") } } } }