package com.alibaba.genie.panel.alarm.viewmodel
import android.app.Activity
import android.app.Application
import android.text.TextUtils
import cn.hutool.core.date.DateTime
import cn.hutool.core.date.DateUtil
import com.alibaba.fastjson.JSON
import com.alibaba.genie.panel.alarm.R
import com.alibaba.genie.panel.alarm.SettingRepository
import com.alibaba.genie.panel.alarm.repository.bean.AlarmBean
import com.alibaba.genie.panel.alarm.ui.utils.AlarmClockUtil
import com.alibaba.genie.panel.alarm.utils.CommonUtil
import com.alibaba.genie.panel.basic.base.SingleLiveData
import com.alibaba.genie.panel.basic.component.event.AlarmClockEvent
import com.alibaba.genie.panel.basic.constant.KeyConstant
import com.alibaba.genie.panel.basic.utils.SettingLog
import com.aliyun.aligeniessp_1_0.models.CreateAlarmRequest
import com.aliyun.aligeniessp_1_0.models.CreateAlarmRequest.CreateAlarmRequestPayloadScheduleInfoOnce
import com.aliyun.aligeniessp_1_0.models.CreateAlarmRequest.CreateAlarmRequestPayloadScheduleInfoStatutoryWorkingDay
import com.aliyun.aligeniessp_1_0.models.CreateAlarmResponse
import com.aliyun.aligeniessp_1_0.models.DeleteAlarmsResponse
import com.aliyun.aligeniessp_1_0.models.ListAlarmsResponseBody
import com.aliyun.aligeniessp_1_0.models.ListMusicResponse
import com.aliyun.aligeniessp_1_0.models.ListMusicResponseBody
import com.aliyun.aligeniessp_1_0.models.UpdateAlarmRequest
import com.aliyun.aligeniessp_1_0.models.UpdateAlarmResponse
import java.util.Date
open class AddClockViewModel(application: Application) : BaseAlarmViewModel(application) {
val deleteLiveData = SingleLiveData<Boolean>()
val pageTitleLiveData = SingleLiveData<String>()
val nivIconLiveData = SingleLiveData<Int>()
val nivRingtoneLiveData = SingleLiveData<String>()
val nivRemarkLiveData = SingleLiveData<String>()
val nivRepeatLiveData = SingleLiveData<Pair<Int, String>>()
var dayOfWeek: IntArray? = null
private val defaultRemarkName: String =
application.getString(R.string.setting_alarm_clock_default_remark)
var iconType: Int = AlarmClockUtil.AlarmIconType.ALARM_ICON_BELL
set(value) {
field = value
nivIconLiveData.value = AlarmClockUtil.getSmallIcon(value)
}
var alarm: AlarmBean? = null
set(value) {
field = value
deleteLiveData.value = (value != null && value.alarmId != 0L)
pageTitleLiveData.value = if (value == null) "添加闹钟" else "编辑闹钟"
val remark: String
val iconType: Int
if (value == null || value.alarmDBInfo == null) {
remark = defaultRemarkName
iconType = AlarmClockUtil.AlarmIconType.ALARM_ICON_BELL
} else {
remark = value.alarmDBInfo.remark
iconType = value.alarmDBInfo.icon
}
val ringtone: String?
if (value == null || value.alarmInfo == null) {
ringtone = "鼓声"
dealRepeat(0, null)
} else {
ringtone = value.alarmInfo.musicInfo?.musicName
processRepeatInfo(value.alarmInfo.scheduleInfo)
}
nivRemarkLiveData.value = remark
this@AddClockViewModel.iconType = iconType
nivRingtoneLiveData.value = ringtone
}
private fun processRepeatInfo(scheduleInfo: ListAlarmsResponseBody.ListAlarmsResponseBodyResultModelScheduleInfo): Unit {
when (scheduleInfo.type) {
KeyConstant.ALARM_SCHEDULE_ONCE -> {
dealRepeat(0, null)
}
KeyConstant.ALARM_SCHEDULE_STATUTORY_WORKING_DAY -> {
dealRepeat(3, null)
}
KeyConstant.ALARM_SCHEDULE_WEEKLY -> {
val weekly = scheduleInfo.weekly
val daysOfWeek = weekly.daysOfWeek
daysOfWeek?.let { week ->
val size = week.size
if (size == 7) {
dealRepeat(1, daysOfWeek.toIntArray())
} else if (size == 5 && week.sum() == 15) {
dealRepeat(2, daysOfWeek.toIntArray())
} else {
dealRepeat(4, daysOfWeek.toIntArray())
}
}
}
}
}
var musicList: List<ListMusicResponseBody.ListMusicResponseBodyResultModel>? = null
get() {
if (field.isNullOrEmpty()) {
field = pref.musicList
}
return field
}
var musicNameList: List<String>? = null
get() {
if (field == null) {
field = musicList?.map { it.musicName }
}
return field
}
var remark: String? = null
set(value) {
field = if (value.isNullOrEmpty()) {
defaultRemarkName
} else {
value
}
nivRemarkLiveData.value = field
}
get() = nivRemarkLiveData.value
var scheduleType: String = KeyConstant.ALARM_SCHEDULE_ONCE
var selectMusicId: Long = 1L
fun dealRepeat(index: Int, dayOfWeek: IntArray?) {
val info = when (index) {
0 -> "单次"
1 -> "每天"
2 -> "工作日"
3 -> "法定工作日"
4 -> parseDayOdWeekToShortStr(dayOfWeek)
else -> ""
}
scheduleType = when (index) {
0 -> KeyConstant.ALARM_SCHEDULE_ONCE
1, 2, 4 -> KeyConstant.ALARM_SCHEDULE_WEEKLY
3 -> KeyConstant.ALARM_SCHEDULE_STATUTORY_WORKING_DAY
else -> KeyConstant.ALARM_SCHEDULE_ONCE
}
this.dayOfWeek = when (index) {
0 -> null
1 -> intArrayOf(1, 2, 3, 4, 5, 6, 7)
2 -> intArrayOf(1, 2, 3, 4, 5)
3 -> null
4 -> dayOfWeek
else -> null
}
nivRepeatLiveData.value = Pair(index, info)
}
fun dealRingtone(index: Int) {
musicList?.get(index)?.let {
selectMusicId = it.musicId
nivRingtoneLiveData.value = it.musicName
}
}
private fun parseDayOdWeekToShortStr(dayOfWeek: IntArray?) = dayOfWeek?.map {
when (it) {
1 -> "一"
2 -> "二"
3 -> "三"
4 -> "四"
5 -> "五"
6 -> "六"
7 -> "日"
else -> {}
}
}?.joinToString("/", prefix = "周") ?: ""
fun performAddClock(
hour: Int,
minute: Int,
) {
if (!checkNetWork()) return
if (alarm == null || alarm!!.alarmId == 0L) {
performAddClock(
scheduleType,
dayOfWeek,
hour,
minute,
selectMusicId,
remark ?: defaultRemarkName,
iconType,
false
)
} else {
performDelAndAddClock {
performAddClock(
scheduleType,
dayOfWeek,
hour,
minute,
selectMusicId,
remark ?: defaultRemarkName,
iconType,
true
)
}
}
}
private fun checkNetWork(): Boolean {
val app = this.getApplication<Application>()
return if (app != null && !CommonUtil.isNetWorkAvailable(app)) {
showToast(app.getString(R.string.setting_alarm_clock_no_network))
false
} else
true
}
private fun performAddClock(
scheduleType: String,
daysOfWeek: IntArray?,
hour: Int,
minute: Int,
musicId: Long,
remark: String,
iconType: Int,
delThenAdd: Boolean
) {
val scheduleInfo =
CreateAlarmRequest.CreateAlarmRequestPayloadScheduleInfo().setType(scheduleType)
when (scheduleType) {
KeyConstant.ALARM_SCHEDULE_ONCE -> scheduleInfo.setOnce(buildOnce(hour, minute))
KeyConstant.ALARM_SCHEDULE_STATUTORY_WORKING_DAY -> scheduleInfo.setStatutoryWorkingDay(
buildWorkingDay(hour, minute)
)
KeyConstant.ALARM_SCHEDULE_WEEKLY -> daysOfWeek?.let {
scheduleInfo.setWeekly(buildWeekly(hour, minute, daysOfWeek))
}
}
val music = getMusicInfoById(musicId)
val musicInfo = CreateAlarmRequest.CreateAlarmRequestPayloadMusicInfo().apply {
setMusicId(music.musicId)
setMusicType(music.musicType)
setMusicName(music.musicName)
setMusicTypeName(music.musicTypeName)
setMusicUrl(music.musicUrl)
}
val volume = 100
SettingLog.w(
TAG,
"createAlarm, scheduleInfo: ${JSON.toJSONString(scheduleInfo)}, musicInfo: ${
JSON.toJSONString(musicInfo)
}, volume: $volume"
)
openApi.createAlarm(
scheduleInfo,
musicInfo,
volume,
object : SettingRepository.OnResponseListener<CreateAlarmResponse> {
override fun onSuccess(response: CreateAlarmResponse) {
if (null == response || null == response.body) {
showToast(if (delThenAdd) "更新失败" else "创建失败")
return
}
if (null == response.body.result) {
showToast(if (TextUtils.isEmpty(response.body.message)) "创建失败" else response.body.message)
return
}
val alarmId = response.body.result
alarmIconRemarkDatabaseHelper.insert(alarmId, remark, iconType)
showToast(if (delThenAdd) "更新成功" else "创建成功")
SettingLog.i(TAG, "createAlarm, result: ${JSON.toJSONString(response)}")
addAlarmClockSuccess()
}
override fun onError(code: String, message: String) {
SettingLog.e(TAG, "createAlarm, error code: ${code}\tmessage: $message")
showToast(if (delThenAdd) "更新失败" else "创建失败")
}
})
}
protected open fun addAlarmClockSuccess() {
finish(Activity.RESULT_OK, null)
}
private fun performDelAndAddClock(runnable: Runnable) {
performDeleteAlarm(
false,
object : SettingRepository.OnResponseListener<DeleteAlarmsResponse?> {
override fun onSuccess(response: DeleteAlarmsResponse?) {
runnable.run()
}
override fun onError(code: String?, message: String?) {
}
})
}
private fun performUpdateClock(
scheduleType: String,
daysOfWeek: IntArray?,
hour: Int,
minute: Int,
musicId: Long,
remark: String,
iconType: Int,
) {
if (alarm == null || alarm!!.alarmId == 0L) {
return
}
val scheduleInfo =
UpdateAlarmRequest.UpdateAlarmRequestPayloadScheduleInfo().setType(scheduleType)
when (scheduleType) {
KeyConstant.ALARM_SCHEDULE_ONCE -> scheduleInfo.setOnce(buildUpdateOnce(hour, minute))
KeyConstant.ALARM_SCHEDULE_STATUTORY_WORKING_DAY -> scheduleInfo.setStatutoryWorkingDay(
buildUpdateWorkingDay(hour, minute)
)
KeyConstant.ALARM_SCHEDULE_WEEKLY -> daysOfWeek?.let {
scheduleInfo.setWeekly(buildUpdateWeekly(hour, minute, daysOfWeek))
}
}
val music = getMusicInfoById(musicId)
val musicInfo = UpdateAlarmRequest.UpdateAlarmRequestPayloadMusicInfo().apply {
setMusicId(music.musicId)
setMusicType(music.musicType)
setMusicName(music.musicName)
setMusicTypeName(music.musicTypeName)
setMusicUrl(music.musicUrl)
}
val volume = 100
SettingLog.w(
TAG,
"updateAlarm, alarmId: ${alarm?.alarmId}, " +
"scheduleInfo: ${JSON.toJSONString(scheduleInfo)}," +
" musicInfo: ${
JSON.toJSONString(musicInfo)
}, volume: $volume"
)
openApi.updateAlarm(
alarm!!.alarmId,
scheduleInfo,
musicInfo,
volume,
object : SettingRepository.OnResponseListener<UpdateAlarmResponse> {
override fun onSuccess(response: UpdateAlarmResponse) {
if (null == response || null == response.body) {
showToast("更新成功")
return
}
if (200 != response.body.code) {
showToast(if (TextUtils.isEmpty(response.body.message)) "更新失败" else response.body.message)
return
}
if (alarm?.alarmDBInfo != null) {
alarmIconRemarkDatabaseHelper.update(alarm!!.alarmId, remark, iconType)
} else {
alarmIconRemarkDatabaseHelper.insert(alarm!!.alarmId, remark, iconType)
}
showToast("更新成功")
SettingLog.i(TAG, "updateAlarm, result: ${JSON.toJSONString(response)}")
finish()
}
override fun onError(code: String, message: String) {
SettingLog.e(TAG, "createAlarm, error code: ${code}\tmessage: $message")
}
})
}
private fun getMusicInfoById(musicId: Long): ListMusicResponseBody.ListMusicResponseBodyResultModel {
musicList?.find { it.musicId == musicId }?.let {
return it
}
return ListMusicResponseBody.ListMusicResponseBodyResultModel().apply {
setMusicId(1L)
setMusicName("鼓声")
setMusicType(15)
setMusicTypeName("经典铃声")
setMusicUrl("http://ailabsaicloudservice.alicdn.com/alarm_music/classics/drum0.mp3")
}
}
private fun buildOnce(hour: Int, minute: Int): CreateAlarmRequestPayloadScheduleInfoOnce? {
val today = getDate(hour, minute)
return CreateAlarmRequestPayloadScheduleInfoOnce().setYear(today.year())
.setMonth(today.monthBaseOne()).setDay(today.dayOfMonth()).setHour(hour)
.setMinute(minute)
}
private fun buildWorkingDay(
hour: Int, minute: Int
): CreateAlarmRequestPayloadScheduleInfoStatutoryWorkingDay? {
return CreateAlarmRequestPayloadScheduleInfoStatutoryWorkingDay().setHour(hour)
.setMinute(minute)
}
private fun buildWeekly(
hour: Int, minute: Int, daysOfWeek: IntArray
): CreateAlarmRequest.CreateAlarmRequestPayloadScheduleInfoWeekly? {
return CreateAlarmRequest.CreateAlarmRequestPayloadScheduleInfoWeekly()
.setDaysOfWeek(daysOfWeek.toList())
.setHour(hour).setMinute(minute)
}
private fun buildUpdateOnce(
hour: Int,
minute: Int
): UpdateAlarmRequest.UpdateAlarmRequestPayloadScheduleInfoOnce? {
val today = getDate(hour, minute)
return UpdateAlarmRequest.UpdateAlarmRequestPayloadScheduleInfoOnce().setYear(today.year())
.setMonth(today.monthBaseOne()).setDay(today.dayOfMonth()).setHour(hour)
.setMinute(minute)
}
private fun buildUpdateWorkingDay(
hour: Int, minute: Int
): UpdateAlarmRequest.UpdateAlarmRequestPayloadScheduleInfoStatutoryWorkingDay? {
return UpdateAlarmRequest.UpdateAlarmRequestPayloadScheduleInfoStatutoryWorkingDay()
.setHour(hour)
.setMinute(minute)
}
private fun buildUpdateWeekly(
hour: Int, minute: Int, daysOfWeek: IntArray
): UpdateAlarmRequest.UpdateAlarmRequestPayloadScheduleInfoWeekly? {
return UpdateAlarmRequest.UpdateAlarmRequestPayloadScheduleInfoWeekly()
.setDaysOfWeek(daysOfWeek.toList())
.setHour(hour).setMinute(minute)
}
private fun getDate(hour: Int, minute: Int): DateTime {
val dateNow = Date()
val nowHour: Int = DateUtil.hour(dateNow, true)
val nowMinute: Int = DateUtil.minute(dateNow)
if (nowHour > hour) {
return DateUtil.tomorrow()
}
return if (nowHour == hour && nowMinute > minute) {
DateUtil.tomorrow()
} else DateUtil.date()
}
override fun onCreate() {
super.onCreate()
checkAndRefreshMusicList()
}
private fun checkAndRefreshMusicList() {
val musicList = this.musicList
if (musicList.isNullOrEmpty()) {
openApi.getMusicList(
15,
"经典铃声",
0,
10,
object : SettingRepository.OnResponseListener<ListMusicResponse> {
override fun onSuccess(response: ListMusicResponse) {
val result = response.body.getResult().model
result?.toMutableList()?.let { musicList ->
musicList.sortBy { it.musicId }
this@AddClockViewModel.musicList = musicList
pref.putMusicList(musicList)
}
}
override fun onError(code: String, message: String) {
SettingLog.e(
TAG, "getMusicList, error code: ${code}\tmessage: $message"
)
}
})
}
}
fun performDeleteAlarm() {
performDeleteAlarm(true, null)
}
private fun performDeleteAlarm(
notify: Boolean,
callback: SettingRepository.OnResponseListener<DeleteAlarmsResponse?>?
) {
if (alarm == null) {
return
}
if (!checkNetWork()) return
openApi.deleteAlarms(
listOf(alarm!!.alarmId),
object : SettingRepository.OnResponseListener<DeleteAlarmsResponse?> {
override fun onSuccess(response: DeleteAlarmsResponse?) {
alarmIconRemarkDatabaseHelper.delete(alarm!!.alarmId)
if (notify) {
showToast("删除成功")
liveBus.post(AlarmClockEvent.EVENT_REQUEST)
finish()
}
callback?.onSuccess(response)
}
override fun onError(code: String?, message: String?) {
SettingLog.e(TAG, "deleteAlarms, error code: ${code}\tmessage: $message")
if (notify) {
showToast("删除失败");
}
callback?.onError(code, message)
}
})
}
companion object {
private const val TAG = KeyConstant.TAG_PREFIX + "AddClockViewModel"
}
}