/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.wifi.details2

import android.content.Context
import android.net.wifi.WifiManager
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.os.Process
import android.os.SimpleClock
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.android.settings.R
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.widget.preference.ListPreferenceModel
import com.android.settingslib.spa.widget.preference.ListPreferenceOption
import com.android.settingslib.spa.widget.preference.RadioPreferences
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Category
import com.android.wifitrackerlib.WifiEntry
import java.time.Clock
import java.time.ZoneOffset
import java.util.Base64

const val WIFI_ENTRY_KEY = "wifiEntryKey"

object WifiPrivacyPageProvider : SettingsPageProvider {
    override val name = "WifiPrivacy"
    const val TAG = "WifiPrivacyPageProvider"

    override val parameter = listOf(
        navArgument(WIFI_ENTRY_KEY) { type = NavType.StringType },
    )

    @Composable
    override fun Page(arguments: Bundle?) {
        val wifiEntryKey =
            String(Base64.getUrlDecoder().decode(arguments!!.getString(WIFI_ENTRY_KEY)))
        if (wifiEntryKey != null) {
            val context = LocalContext.current
            val lifecycle = LocalLifecycleOwner.current.lifecycle
            val wifiEntry = remember {
                getWifiEntry(context, wifiEntryKey, lifecycle)
            }
            WifiPrivacyPage(wifiEntry)
        }
    }

    fun getRoute(
        wifiEntryKey: String,
    ): String = "${name}/${Base64.getUrlEncoder().encodeToString(wifiEntryKey.toByteArray())}"
}

@Composable
fun WifiPrivacyPage(wifiEntry: WifiEntry) {
    val isSelectable: Boolean = wifiEntry.canSetPrivacy()
    RegularScaffold(
        title = stringResource(id = R.string.wifi_privacy_settings)
    ) {
        Column {
            val title = stringResource(id = R.string.wifi_privacy_mac_settings)
            val wifiPrivacyEntries = stringArrayResource(R.array.wifi_privacy_entries)
            val wifiPrivacyValues = stringArrayResource(R.array.wifi_privacy_values)
            val textsSelectedId = rememberSaveable { mutableIntStateOf(wifiEntry.privacy) }
            val dataList = remember {
                wifiPrivacyEntries.mapIndexed { index, text ->
                    ListPreferenceOption(id = wifiPrivacyValues[index].toInt(), text = text)
                }
            }
            RadioPreferences(remember {
                object : ListPreferenceModel {
                    override val title = title
                    override val options = dataList
                    override val selectedId = textsSelectedId
                    override val onIdSelected: (Int) -> Unit = {
                        textsSelectedId.intValue = it
                        onSelectedChange(wifiEntry, it)
                    }
                    override val enabled = { isSelectable }
                }
            })
            wifiEntry.wifiConfiguration?.let {
                DeviceNameSwitchPreference(wifiEntry)
            }
        }
    }
}

@Composable
fun DeviceNameSwitchPreference(wifiEntry: WifiEntry) {
    val title = stringResource(id = R.string.wifi_privacy_device_name_settings)
    Category(title = title) {
        var checked by remember {
            mutableStateOf(wifiEntry.wifiConfiguration?.isSendDhcpHostnameEnabled)
        }
        val context = LocalContext.current
        val wifiManager = context.getSystemService(WifiManager::class.java)!!
        SwitchPreference(object : SwitchPreferenceModel {
            override val title =
                context.resources.getString(
                    R.string.wifi_privacy_send_device_name_toggle_title
                )
            override val summary =
                {
                    context.resources.getString(
                        R.string.wifi_privacy_send_device_name_toggle_summary
                    )
                }
            override val checked = { checked }
            override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
                wifiEntry.wifiConfiguration?.let {
                    it.isSendDhcpHostnameEnabled = newChecked
                    wifiManager.save(it, null /* listener */)
                    checked = newChecked
                }
            }
        })
    }
}

fun onSelectedChange(wifiEntry: WifiEntry, privacy: Int) {
    if (wifiEntry.privacy == privacy) {
        // Prevent disconnection + reconnection if settings not changed.
        return
    }
    wifiEntry.setPrivacy(privacy)

    // To activate changing, we need to reconnect network. WiFi will auto connect to
    // current network after disconnect(). Only needed when this is connected network.

    // To activate changing, we need to reconnect network. WiFi will auto connect to
    // current network after disconnect(). Only needed when this is connected network.
    if (wifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
        wifiEntry.disconnect(null /* callback */)
        wifiEntry.connect(null /* callback */)
    }
}

fun getWifiEntry(
    context: Context,
    wifiEntryKey: String,
    liftCycle: androidx.lifecycle.Lifecycle
): WifiEntry {
    // Max age of tracked WifiEntries
    val MAX_SCAN_AGE_MILLIS: Long = 15000
    // Interval between initiating SavedNetworkTracker scans
    val SCAN_INTERVAL_MILLIS: Long = 10000
    val mWorkerThread = HandlerThread(
        WifiPrivacyPageProvider.TAG,
        Process.THREAD_PRIORITY_BACKGROUND
    )
    mWorkerThread.start()
    val elapsedRealtimeClock: Clock = object : SimpleClock(ZoneOffset.UTC) {
        override fun millis(): Long {
            return android.os.SystemClock.elapsedRealtime()
        }
    }
    val mNetworkDetailsTracker = featureFactory
        .wifiTrackerLibProvider
        .createNetworkDetailsTracker(
            liftCycle,
            context,
            Handler(Looper.getMainLooper()),
            mWorkerThread.getThreadHandler(),
            elapsedRealtimeClock,
            MAX_SCAN_AGE_MILLIS,
            SCAN_INTERVAL_MILLIS,
            wifiEntryKey
        )
    return mNetworkDetailsTracker.wifiEntry
}
