<commit_before>package io.particle.mesh.setup.flow

import android.app.Application
import androidx.annotation.MainThread
import androidx.annotation.StringRes
import androidx.lifecycle.LiveData
import com.snakydesign.livedataextensions.liveDataOf
import com.squareup.okhttp.OkHttpClient
import io.particle.android.sdk.cloud.ParticleCloud
import io.particle.android.sdk.cloud.ParticleDevice
import io.particle.mesh.bluetooth.connecting.BluetoothConnectionManager
import io.particle.mesh.common.android.livedata.awaitUpdate
import io.particle.mesh.common.android.livedata.castAndPost
import io.particle.mesh.common.android.livedata.nonNull
import io.particle.mesh.ota.FirmwareUpdateManager
import io.particle.mesh.setup.BarcodeData.CompleteBarcodeData
import io.particle.mesh.setup.connection.ProtocolTransceiver
import io.particle.mesh.setup.connection.ProtocolTransceiverFactory
import io.particle.mesh.setup.connection.security.SecurityManager
import io.particle.mesh.setup.flow.context.SetupContexts
import kotlinx.coroutines.Job
import mu.KotlinLogging


fun buildFlowManager(
    app: Application,
    cloud: ParticleCloud,
    dialogTool: DialogTool,
    flowUi: FlowUiDelegate,
    flowTerminator: MeshFlowTerminator,
    okHttpClient: OkHttpClient = OkHttpClient(),
    securityManager: SecurityManager = SecurityManager()
): MeshFlowRunner {
    val btConMan = BluetoothConnectionManager(app)
    val transceiverFactory = ProtocolTransceiverFactory(securityManager)
    val deviceConnector = DeviceConnector(cloud, btConMan, transceiverFactory)

    val fwUpdateManager = FirmwareUpdateManager(cloud, okHttpClient)

    val deps = StepDeps(
        cloud,
        deviceConnector,
        fwUpdateManager,
        dialogTool,
        flowUi
    )

    return MeshFlowRunner(deps, app, flowTerminator)
}


class MeshFlowTerminator {

    val shouldTerminateFlowLD: LiveData<Boolean> = liveDataOf(false)

    fun terminateFlow() {
        shouldTerminateFlowLD.castAndPost(true)
    }
}


enum class FlowIntent {
    FIRST_TIME_SETUP,
    SINGLE_TASK_FLOW
}


enum class FlowType {
    PREFLOW,
    JOINER_FLOW,
    INTERNET_CONNECTED_PREFLOW,
    ETHERNET_FLOW,

    WIFI_FLOW,
    CELLULAR_FLOW,
    NETWORK_CREATOR_POSTFLOW,
    STANDALONE_POSTFLOW,

    CONTROL_PANEL_PREFLOW,

    CONTROL_PANEL_CELLULAR_PRESENT_OPTIONS_FLOW,
    CONTROL_PANEL_CELLULAR_SET_NEW_DATA_LIMIT,
    CONTROL_PANEL_CELLULAR_SIM_DEACTIVATE,
    CONTROL_PANEL_CELLULAR_SIM_REACTIVATE,
    CONTROL_PANEL_CELLULAR_SIM_UNPAUSE,
    CONTROL_PANEL_CELLULAR_SIM_ACTION_POSTFLOW,

    CONTROL_PANEL_MESH_INSPECT_NETWORK_FLOW,
    CONTROL_PANEL_MESH_ADD_PREFLOW,
    CONTROL_PANEL_MESH_JOINER_FLOW,
    CONTROL_PANEL_MESH_CREATE_NETWORK_FLOW,
    CONTROL_PANEL_MESH_LEAVE_NETWORK_FLOW,

    CONTROL_PANEL_WIFI_INSPECT_NETWORK_FLOW,
    CONTROL_PANEL_WIFI_ADD_NETWORK_FLOW,
    CONTROL_PANEL_WIFI_MANAGE_NETWORKS_FLOW,

    CONTROL_PANEL_ETHERNET_PRESENT_OPTIONS_FLOW,
    CONTROL_PANEL_ETHERNET_TOGGLE_PINS_FLOW
}


class MeshFlowRunner(
    private val deps: StepDeps,
    private val everythingNeedsAContext: Application,
    flowTerminator: MeshFlowTerminator
) {

    private val log = KotlinLogging.logger {}

    // set up a placeholder listener that will be overwritten when a new flow starts
    val listener: FlowRunnerUiListener
        get() = flowExecutor.listener

    private val flowExecutor = MeshFlowExecutor(deps, flowTerminator)


    @MainThread
    fun startFlow() {
        log.info { "startFlow()" }
        flowExecutor.executeNewFlow(
            FlowIntent.FIRST_TIME_SETUP,
            listOf(FlowType.PREFLOW),
            SetupContexts()
        )
    }

    @MainThread
    fun startNewFlowWithCommissioner() {
        log.info { "startNewFlowWithCommissioner()" }

//        val oldContexts = contexts!!
        flowExecutor.executeNewFlow(
            FlowIntent.FIRST_TIME_SETUP,
            listOf(FlowType.PREFLOW),
            SetupContexts()
        )
//        val newContexts = contexts!!
    }

    @MainThread
    fun startControlPanelWifiConfigFlow(device: ParticleDevice, barcode: CompleteBarcodeData) {
        val scopes = Scopes()
        scopes.onMain {
            val ctxs = initContextWithDeviceIdAndBarcode(device, barcode, scopes)

            ctxs.cloud.updatePricingImpactConfirmed(true)
            ctxs.cloud.updateShouldConnectToDeviceCloudConfirmed(true)
            ctxs.singleStepCongratsMessage = "Wi-Fi credentials were successfully added"

            flowExecutor.executeNewFlow(
                FlowIntent.SINGLE_TASK_FLOW,
                listOf(
                    FlowType.CONTROL_PANEL_PREFLOW,
                    FlowType.CONTROL_PANEL_WIFI_ADD_NETWORK_FLOW
                ),
                ctxs
            )
        }
    }

    @MainThread
    fun startControlPanelInspectCurrentWifiNetworkFlow(
        device: ParticleDevice,
        barcode: CompleteBarcodeData
    ) {
        val scopes = Scopes()
        scopes.onMain {
            val ctxs = initContextWithDeviceIdAndBarcode(device, barcode, scopes)

            flowExecutor.executeNewFlow(
                FlowIntent.SINGLE_TASK_FLOW,
                listOf(
                    FlowType.CONTROL_PANEL_PREFLOW,
                    FlowType.CONTROL_PANEL_WIFI_INSPECT_NETWORK_FLOW
                ),
                ctxs
            )
        }
    }

    @MainThread
    fun startShowControlPanelCellularOptionsFlow(device: ParticleDevice) {
        val ctxs = initContextForSimFlow(device)

        flowExecutor.executeNewFlow(
            FlowIntent.SINGLE_TASK_FLOW,
            listOf(FlowType.CONTROL_PANEL_CELLULAR_PRESENT_OPTIONS_FLOW),
            ctxs
        )
    }

    @MainThread
    fun startControlPanelMeshInspectCurrentNetworkFlow(
        device: ParticleDevice,
        barcode: CompleteBarcodeData
    ) {
        val scopes = Scopes()
        scopes.onMain {
            val ctxs = initContextWithDeviceIdAndBarcode(device, barcode, scopes)

            flowExecutor.executeNewFlow(
                FlowIntent.SINGLE_TASK_FLOW,
                listOf(
                    FlowType.CONTROL_PANEL_PREFLOW,
                    FlowType.CONTROL_PANEL_MESH_INSPECT_NETWORK_FLOW
                ),
                ctxs
            )
        }
    }

    @MainThread
    fun startControlPanelManageWifiNetworksFlow(
        device: ParticleDevice,
        barcode: CompleteBarcodeData
    ) {
        val scopes = Scopes()
        scopes.onMain {
            val ctxs = initContextWithDeviceIdAndBarcode(device, barcode, scopes)
<commit_msg>Don't waste time on firmware update checks when we don't need them<commit_after>package io.particle.mesh.setup.flow

import android.app.Application
import androidx.annotation.MainThread
import androidx.annotation.StringRes
import androidx.lifecycle.LiveData
import com.snakydesign.livedataextensions.liveDataOf
import com.squareup.okhttp.OkHttpClient
import io.particle.android.sdk.cloud.ParticleCloud
import io.particle.android.sdk.cloud.ParticleDevice
import io.particle.mesh.bluetooth.connecting.BluetoothConnectionManager
import io.particle.mesh.common.android.livedata.awaitUpdate
import io.particle.mesh.common.android.livedata.castAndPost
import io.particle.mesh.common.android.livedata.nonNull
import io.particle.mesh.ota.FirmwareUpdateManager
import io.particle.mesh.setup.BarcodeData.CompleteBarcodeData
import io.particle.mesh.setup.connection.ProtocolTransceiver
import io.particle.mesh.setup.connection.ProtocolTransceiverFactory
import io.particle.mesh.setup.connection.security.SecurityManager
import io.particle.mesh.setup.flow.context.SetupContexts
import kotlinx.coroutines.Job
import mu.KotlinLogging


fun buildFlowManager(
    app: Application,
    cloud: ParticleCloud,
    dialogTool: DialogTool,
    flowUi: FlowUiDelegate,
    flowTerminator: MeshFlowTerminator,
    okHttpClient: OkHttpClient = OkHttpClient(),
    securityManager: SecurityManager = SecurityManager()
): MeshFlowRunner {
    val btConMan = BluetoothConnectionManager(app)
    val transceiverFactory = ProtocolTransceiverFactory(securityManager)
    val deviceConnector = DeviceConnector(cloud, btConMan, transceiverFactory)

    val fwUpdateManager = FirmwareUpdateManager(cloud, okHttpClient)

    val deps = StepDeps(
        cloud,
        deviceConnector,
        fwUpdateManager,
        dialogTool,
        flowUi
    )

    return MeshFlowRunner(deps, app, flowTerminator)
}


class MeshFlowTerminator {

    val shouldTerminateFlowLD: LiveData<Boolean> = liveDataOf(false)

    fun terminateFlow() {
        shouldTerminateFlowLD.castAndPost(true)
    }
}


enum class FlowIntent {
    FIRST_TIME_SETUP,
    SINGLE_TASK_FLOW
}


enum class FlowType {
    PREFLOW,
    JOINER_FLOW,
    INTERNET_CONNECTED_PREFLOW,
    ETHERNET_FLOW,

    WIFI_FLOW,
    CELLULAR_FLOW,
    NETWORK_CREATOR_POSTFLOW,
    STANDALONE_POSTFLOW,

    CONTROL_PANEL_PREFLOW,

    CONTROL_PANEL_CELLULAR_PRESENT_OPTIONS_FLOW,
    CONTROL_PANEL_CELLULAR_SET_NEW_DATA_LIMIT,
    CONTROL_PANEL_CELLULAR_SIM_DEACTIVATE,
    CONTROL_PANEL_CELLULAR_SIM_REACTIVATE,
    CONTROL_PANEL_CELLULAR_SIM_UNPAUSE,
    CONTROL_PANEL_CELLULAR_SIM_ACTION_POSTFLOW,

    CONTROL_PANEL_MESH_INSPECT_NETWORK_FLOW,
    CONTROL_PANEL_MESH_ADD_PREFLOW,
    CONTROL_PANEL_MESH_JOINER_FLOW,
    CONTROL_PANEL_MESH_CREATE_NETWORK_FLOW,
    CONTROL_PANEL_MESH_LEAVE_NETWORK_FLOW,

    CONTROL_PANEL_WIFI_INSPECT_NETWORK_FLOW,
    CONTROL_PANEL_WIFI_ADD_NETWORK_FLOW,
    CONTROL_PANEL_WIFI_MANAGE_NETWORKS_FLOW,

    CONTROL_PANEL_ETHERNET_PRESENT_OPTIONS_FLOW,
    CONTROL_PANEL_ETHERNET_TOGGLE_PINS_FLOW
}


class MeshFlowRunner(
    private val deps: StepDeps,
    private val everythingNeedsAContext: Application,
    flowTerminator: MeshFlowTerminator
) {

    private val log = KotlinLogging.logger {}

    // set up a placeholder listener that will be overwritten when a new flow starts
    val listener: FlowRunnerUiListener
        get() = flowExecutor.listener

    private val flowExecutor = MeshFlowExecutor(deps, flowTerminator)


    @MainThread
    fun startFlow() {
        log.info { "startFlow()" }
        flowExecutor.executeNewFlow(
            FlowIntent.FIRST_TIME_SETUP,
            listOf(FlowType.PREFLOW),
            SetupContexts()
        )
    }

    @MainThread
    fun startNewFlowWithCommissioner() {
        log.info { "startNewFlowWithCommissioner()" }

//        val oldContexts = contexts!!
        flowExecutor.executeNewFlow(
            FlowIntent.FIRST_TIME_SETUP,
            listOf(FlowType.PREFLOW),
            SetupContexts()
        )
//        val newContexts = contexts!!
    }

    @MainThread
    fun startControlPanelWifiConfigFlow(device: ParticleDevice, barcode: CompleteBarcodeData) {
        val scopes = Scopes()
        scopes.onMain {
            val ctxs = initContextWithDeviceIdAndBarcode(device, barcode, scopes)

            ctxs.cloud.updatePricingImpactConfirmed(true)
            ctxs.cloud.updateShouldConnectToDeviceCloudConfirmed(true)
            ctxs.singleStepCongratsMessage = "Wi-Fi credentials were successfully added"
            ctxs.targetDevice.hasLatestFirmware = true  // skip the firmware update at this stage

            flowExecutor.executeNewFlow(
                FlowIntent.SINGLE_TASK_FLOW,
                listOf(
                    FlowType.CONTROL_PANEL_PREFLOW,
                    FlowType.CONTROL_PANEL_WIFI_ADD_NETWORK_FLOW
                ),
                ctxs
            )
        }
    }

    @MainThread
    fun startControlPanelInspectCurrentWifiNetworkFlow(
        device: ParticleDevice,
        barcode: CompleteBarcodeData
    ) {
        val scopes = Scopes()
        scopes.onMain {
            val ctxs = initContextWithDeviceIdAndBarcode(device, barcode, scopes)

            flowExecutor.executeNewFlow(
                FlowIntent.SINGLE_TASK_FLOW,
                listOf(
                    FlowType.CONTROL_PANEL_PREFLOW,
                    FlowType.CONTROL_PANEL_WIFI_INSPECT_NETWORK_FLOW
                ),
                ctxs
            )
        }
    }

    @MainThread
    fun startShowControlPanelCellularOptionsFlow(device: ParticleDevice) {
        val ctxs = initContextForSimFlow(device)

        flowExecutor.executeNewFlow(
            FlowIntent.SINGLE_TASK_FLOW,
            listOf(FlowType.CONTROL_PANEL_CELLULAR_PRESENT_OPTIONS_FLOW),
            ctxs
        )
    }

    @MainThread
    fun startControlPanelMeshInspectCurrentNetworkFlow(
        device: ParticleDevice,
        barcode: CompleteBarcodeData
    ) {
        val scopes = Scopes()
        scopes.onMain {
            val ctxs = initContextWithDeviceIdAndBarcode(device, barcode, scopes)

            flowExecutor.executeNewFlow(
                FlowIntent.SINGLE_TASK_FLOW,
                listOf(
                    FlowType.CONTROL_PANEL_PREFLOW,
                    FlowType.CONTROL_PANEL_MESH_INSPECT_NETWORK_FLOW
                ),
                ctxs
            )
        }
    }

    @MainThread
    fun startControlPanelManageWifiNetworksFlow(
        device: ParticleDevice,
        barcode: CompleteBarcodeData
    ) {
        val scopes = Scopes()
        scopes.onMain {
            val ctxs = initContextWithDeviceIdAndBarcode(device, barcode, scopes)
            ctxs.targetDevice.hasLatestFirmware = true  // skip the firmware update at this stage

{'fraction_non_alphanumeric': 0.060497423257898274, 'fraction_numerical': 0.0, 'mean_word_length': 2.8901801278326555, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4626657', 'n_tokens_mistral': 4285, 'n_tokens_neox': 4073, 'n_words': 617}