/*
 * QAuxiliary - An Xposed module for QQ/TIM
 * Copyright (C) 2019-2022 qwq233@qwq2333.top
 * https://github.com/cinit/QAuxiliary
 *
 * This software is non-free but opensource software: you can redistribute it
 * and/or modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation; either
 * version 3 of the License, or any later version and our eula as published
 * by QAuxiliary contributors.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * and eula along with this software.  If not, see
 * <https://www.gnu.org/licenses/>
 * <https://github.com/cinit/QAuxiliary/blob/master/LICENSE.md>.
 */

package io.github.qauxv.hook

import android.app.Activity
import android.content.Context
import android.view.View
import cc.microblock.hook.pangu_spacing
import io.github.qauxv.base.ISwitchCellAgent
import io.github.qauxv.base.IUiItemAgent
import io.github.qauxv.util.SyncUtils
import io.github.qauxv.util.dexkit.DexKitTarget
import kotlinx.coroutines.flow.StateFlow

/**
 * A function that has a custom configuration UI. They usually do NOT have a switch.
 */
abstract class CommonConfigFunctionHook(
    hookKey: String? = null,
    defaultEnabled: Boolean = false,
    targets: Array<DexKitTarget>? = null,
    private val targetProc: Int = SyncUtils.PROC_MAIN
) : BaseFunctionHook(hookKey, defaultEnabled, targets) {
    constructor() : this(null, false)
    constructor(defaultEnabled: Boolean) : this(null, defaultEnabled)
    constructor(key: String) : this(key, false)
    constructor(key: String, targets: Array<DexKitTarget>?) : this(key, false, targets)
    constructor(targets: Array<DexKitTarget>) : this(null, false, targets)
    constructor(key: String, targetProc: Int) : this(hookKey = key, targetProc = targetProc)
    constructor(targetProc: Int) : this(null, targetProc = targetProc)
    constructor(targetProc: Int, targets: Array<DexKitTarget>) : this(null, targetProc = targetProc, targets = targets)

    /**
     * Name of the function.
     */
    abstract val name: String

    /**
     * The current human-readable state of the function(optional).
     * Keep it as short as possible(e.g. "5 enabled", "disabled", no more than 10 characters).
     */
    abstract val valueState: StateFlow<String?>?

    /**
     * Called when the function UI item is clicked.
     */
    abstract val onUiItemClickListener: ((IUiItemAgent, Activity, View) -> Unit)

    /**
     * Description of the function.
     */
    open val description: CharSequence? = null

    override val targetProcesses = targetProc

    open val extraSearchKeywords: Array<String>? = null

    override val uiItemAgent by lazy { uiItemAgent() }
    private fun uiItemAgent() = object : IUiItemAgent {
        override val titleProvider: (IUiItemAgent) -> String = { _ -> pangu_spacing(name) }
        override val summaryProvider: (IUiItemAgent, Context) -> CharSequence? = { _, _ ->
            if(description is String)
                pangu_spacing(description.toString())
            else description
         }
        override val valueState: StateFlow<String?>?
            get() = this@CommonConfigFunctionHook.valueState
        override val validator: ((IUiItemAgent) -> Boolean) = { _ -> true }
        override val switchProvider: ISwitchCellAgent? = null
        override val onClickListener: ((IUiItemAgent, Activity, View) -> Unit) = onUiItemClickListener
        override val extraSearchKeywordProvider: ((IUiItemAgent, Context) -> Array<String>?)?
            get() = extraSearchKeywords?.let { { _, _ -> it } }
    }

}
