<commit_before>package org.owntracks.android.support

import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import org.eclipse.paho.client.mqttv3.MqttConnectOptions
import org.greenrobot.eventbus.EventBus
import org.owntracks.android.BuildConfig
import org.owntracks.android.R
import org.owntracks.android.injection.qualifier.AppContext
import org.owntracks.android.injection.scopes.PerApplication
import org.owntracks.android.messages.MessageConfiguration
import org.owntracks.android.services.LocationProcessor
import org.owntracks.android.services.MessageProcessorEndpointHttp
import org.owntracks.android.services.MessageProcessorEndpointMqtt
import org.owntracks.android.services.worker.Scheduler
import org.owntracks.android.support.Events.ModeChanged
import org.owntracks.android.support.Events.MonitoringChanged
import org.owntracks.android.support.preferences.OnModeChangedPreferenceChangedListener
import org.owntracks.android.support.preferences.PreferencesStore
import timber.log.Timber
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.lang.reflect.Type
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject

@PerApplication
class Preferences @Inject constructor(@AppContext c: Context, private val eventBus: EventBus?, private val preferencesStore: PreferencesStore) {
    private val context: Context = c
    private var isFirstStart = false
    private var currentMode = MessageProcessorEndpointMqtt.MODE_ID

    val sharedPreferencesName: String
        get() = preferencesStore.getSharedPreferencesName()

    init {
        val modePreferenceKey = getPreferenceKey(R.string.preferenceKeyModeId)
        val initMode = preferencesStore.getInitMode(
                modePreferenceKey,
                getIntResource(R.integer.valModeId))
        setMode(initMode, true)
    }

    fun exportToMessage(): MessageConfiguration {
        val cfg = MessageConfiguration()
        cfg[getPreferenceKey(R.string.preferenceKeyVersion)] = BuildConfig.VERSION_CODE
        exportMethods.forEach {
            val annotation = it.getAnnotation(Export::class.java)
            if (annotation != null) {
                cfg[getPreferenceKey(annotation.keyResId)] = it.invoke(this)
            }
        }
        return cfg
    }

    // need to iterated thought hierarchy in order to retrieve methods from above the current instance
    // iterate though the list of methods declared in the class represented by klass variable, and insert those annotated with the specified annotation
    private val exportMethods: List<Method>
        get() {
            val methods: MutableList<Method> = ArrayList()
            var klass: Class<*>? = Preferences::class.java
            while (klass != Any::class.java) { // need to iterated thought hierarchy in order to retrieve methods from above the current instance
                // iterate though the list of methods declared in the class represented by klass variable, and insert those annotated with the specified annotation
                val allMethods = listOf(*klass!!.declaredMethods)
                for (method in allMethods) {
                    if (method.isAnnotationPresent(Export::class.java)) {
                        val annotInstance = method.getAnnotation(Export::class.java)
                        if (currentMode == MessageProcessorEndpointMqtt.MODE_ID && annotInstance.exportModeMqtt || currentMode == MessageProcessorEndpointHttp.MODE_ID && annotInstance.exportModeHttp) {
                            methods.add(method)
                        }
                    }
                }
                // move to the upper class in the hierarchy in search for more methods
                klass = klass.superclass
            }
            return methods
        }

    val importKeys: List<String>
        get() = ArrayList(importMethods.keys)


    private fun Class<*>.parentClasses(): Sequence<Class<*>> {
        var k = this
        return sequence {
            yield(k)
            while (k.superclass != null) {
                k = k.superclass!!
                yield(k)
            }
        }
    }

    // need to iterated thought hierarchy in order to retrieve methods from above the current instance
    // iterate though the list of methods declared in the class represented by klass variable, and insert those annotated with the specified annotation
    private val importMethods: Map<String, Method>
        get() = Preferences::class.java
                .parentClasses()
                .flatMap { it.declaredMethods.asSequence() }
                .filter { it.isAnnotationPresent(Import::class.java) }
                .map { Pair(getPreferenceKey(it.getAnnotation(Import::class.java)!!.keyResId), it) }
                .toMap()


    fun registerOnPreferenceChangedListener(listener: OnModeChangedPreferenceChangedListener?) {
        preferencesStore.registerOnSharedPreferenceChangeListener(listener!!)
    }

    fun unregisterOnPreferenceChangedListener(listener: OnModeChangedPreferenceChangedListener?) {
        preferencesStore.unregisterOnSharedPreferenceChangeListener(listener!!)
    }

    fun checkFirstStart() {
        if (preferencesStore.getBoolean(getPreferenceKey(R.string.preferenceKeyFirstStart), true)) {
            Timber.v("Initial application launch")
            isFirstStart = true
            preferencesStore.putBoolean(getPreferenceKey(R.string.preferenceKeyFirstStart), false)<commit_msg>Simplified preferences export methods<commit_after>package org.owntracks.android.support

import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import org.eclipse.paho.client.mqttv3.MqttConnectOptions
import org.greenrobot.eventbus.EventBus
import org.owntracks.android.BuildConfig
import org.owntracks.android.R
import org.owntracks.android.injection.qualifier.AppContext
import org.owntracks.android.injection.scopes.PerApplication
import org.owntracks.android.messages.MessageConfiguration
import org.owntracks.android.services.LocationProcessor
import org.owntracks.android.services.MessageProcessorEndpointHttp
import org.owntracks.android.services.MessageProcessorEndpointMqtt
import org.owntracks.android.services.worker.Scheduler
import org.owntracks.android.support.Events.ModeChanged
import org.owntracks.android.support.Events.MonitoringChanged
import org.owntracks.android.support.preferences.OnModeChangedPreferenceChangedListener
import org.owntracks.android.support.preferences.PreferencesStore
import timber.log.Timber
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.lang.reflect.Type
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject

@PerApplication
class Preferences @Inject constructor(@AppContext c: Context, private val eventBus: EventBus?, private val preferencesStore: PreferencesStore) {
    private val context: Context = c
    private var isFirstStart = false
    private var currentMode = MessageProcessorEndpointMqtt.MODE_ID

    val sharedPreferencesName: String
        get() = preferencesStore.getSharedPreferencesName()

    init {
        val modePreferenceKey = getPreferenceKey(R.string.preferenceKeyModeId)
        val initMode = preferencesStore.getInitMode(
                modePreferenceKey,
                getIntResource(R.integer.valModeId))
        setMode(initMode, true)
    }

    fun exportToMessage(): MessageConfiguration {
        val cfg = MessageConfiguration()
        cfg[getPreferenceKey(R.string.preferenceKeyVersion)] = BuildConfig.VERSION_CODE
        exportMethods.forEach {
            val annotation = it.getAnnotation(Export::class.java)
            if (annotation != null) {
                cfg[getPreferenceKey(annotation.keyResId)] = it.invoke(this)
            }
        }
        return cfg
    }


    // need to iterated thought hierarchy in order to retrieve methods from above the current instance
    // iterate though the list of methods declared in the class represented by klass variable, and insert those annotated with the specified annotation
    private val exportMethods: List<Method>
        get() = Preferences::class.java
                .parentClasses()
                .flatMap { it.declaredMethods.asSequence() }
                .filter { it.isAnnotationPresent(Export::class.java) }
                .filter {
                    val annotation = it.getAnnotation(Export::class.java)
                    annotation != null &&
                            (currentMode == MessageProcessorEndpointMqtt.MODE_ID && annotation.exportModeMqtt ||
                                    currentMode == MessageProcessorEndpointHttp.MODE_ID && annotation.exportModeHttp)
                }
                .toList()
    
    val importKeys: List<String>
        get() = ArrayList(importMethods.keys)


    // need to iterated thought hierarchy in order to retrieve methods from above the current instance
    // iterate though the list of methods declared in the class represented by klass variable, and insert those annotated with the specified annotation
    private val importMethods: Map<String, Method>
        get() = Preferences::class.java
                .parentClasses()
                .flatMap { it.declaredMethods.asSequence() }
                .filter { it.isAnnotationPresent(Import::class.java) }
                .map { Pair(getPreferenceKey(it.getAnnotation(Import::class.java)!!.keyResId), it) }
                .toMap()

    private fun Class<*>.parentClasses(): Sequence<Class<*>> {
        var k = this
        return sequence {
            yield(k)
            while (k.superclass != null) {
                k = k.superclass!!
                yield(k)
            }
        }
    }

    fun registerOnPreferenceChangedListener(listener: OnModeChangedPreferenceChangedListener?) {
        preferencesStore.registerOnSharedPreferenceChangeListener(listener!!)
    }

    fun unregisterOnPreferenceChangedListener(listener: OnModeChangedPreferenceChangedListener?) {
        preferencesStore.unregisterOnSharedPreferenceChangeListener(listener!!)
    }

    fun checkFirstStart() {
        if (preferencesStore.getBoolean(getPreferenceKey(R.string.preferenceKeyFirstStart), true)) {
            Timber.v("Initial application launch")
            isFirstStart = true
            preferencesStore.putBoolean(getPreferenceKey(R.string.preferenceKeyFirstStart), false)
{'fraction_non_alphanumeric': 0.07707679132172424, 'fraction_numerical': 0.0001903130649919117, 'mean_word_length': 3.0485362095531587, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4741646', 'n_tokens_mistral': 2650, 'n_tokens_neox': 2542, 'n_words': 608}