1094c4dddSWill Schurman // Copyright 2015-present 650 Industries. All rights reserved.
2094c4dddSWill Schurman package host.exp.exponent.di
3094c4dddSWill Schurman 
4094c4dddSWill Schurman import android.app.Application
5094c4dddSWill Schurman import android.content.Context
6094c4dddSWill Schurman import android.os.Handler
7094c4dddSWill Schurman import android.os.Looper
8094c4dddSWill Schurman import com.facebook.proguard.annotations.DoNotStrip
9094c4dddSWill Schurman import expo.modules.updates.db.DatabaseHolder
10094c4dddSWill Schurman import expo.modules.updates.db.UpdatesDatabase
11094c4dddSWill Schurman import host.exp.exponent.ExpoHandler
12094c4dddSWill Schurman import host.exp.exponent.ExponentManifest
13094c4dddSWill Schurman import host.exp.exponent.analytics.EXL
14094c4dddSWill Schurman import host.exp.exponent.kernel.services.ExpoKernelServiceRegistry
15094c4dddSWill Schurman import host.exp.exponent.network.ExponentNetwork
16094c4dddSWill Schurman import host.exp.exponent.storage.ExponentSharedPreferences
17094c4dddSWill Schurman import java.lang.reflect.Field
18094c4dddSWill Schurman import javax.inject.Inject
19094c4dddSWill Schurman 
20094c4dddSWill Schurman class NativeModuleDepsProvider(application: Application) {
21094c4dddSWill Schurman   @Inject
22094c4dddSWill Schurman   @DoNotStrip
23094c4dddSWill Schurman   val mContext: Context = application
24094c4dddSWill Schurman 
25094c4dddSWill Schurman   @Inject
26094c4dddSWill Schurman   @DoNotStrip
27094c4dddSWill Schurman   val mApplicationContext: Application = application
28094c4dddSWill Schurman 
29094c4dddSWill Schurman   @Inject
30094c4dddSWill Schurman   @DoNotStrip
31094c4dddSWill Schurman   val mExpoHandler: ExpoHandler = ExpoHandler(Handler(Looper.getMainLooper()))
32094c4dddSWill Schurman 
33094c4dddSWill Schurman   @Inject
34094c4dddSWill Schurman   @DoNotStrip
35094c4dddSWill Schurman   val mExponentSharedPreferences: ExponentSharedPreferences = ExponentSharedPreferences(mContext)
36094c4dddSWill Schurman 
37094c4dddSWill Schurman   @Inject
38094c4dddSWill Schurman   @DoNotStrip
39094c4dddSWill Schurman   val mExponentNetwork: ExponentNetwork = ExponentNetwork(mContext, mExponentSharedPreferences)
40094c4dddSWill Schurman 
41094c4dddSWill Schurman   @Inject
42094c4dddSWill Schurman   @DoNotStrip
43*d88f0633SWill Schurman   var mExponentManifest: ExponentManifest = ExponentManifest(mContext, mExponentSharedPreferences)
44094c4dddSWill Schurman 
45094c4dddSWill Schurman   @Inject
46094c4dddSWill Schurman   @DoNotStrip
47094c4dddSWill Schurman   var mKernelServiceRegistry: ExpoKernelServiceRegistry = ExpoKernelServiceRegistry(mContext, mExponentSharedPreferences)
48094c4dddSWill Schurman 
49094c4dddSWill Schurman   @Inject
50094c4dddSWill Schurman   @DoNotStrip
51094c4dddSWill Schurman   val mUpdatesDatabaseHolder: DatabaseHolder = DatabaseHolder(UpdatesDatabase.getInstance(mContext))
52094c4dddSWill Schurman 
53094c4dddSWill Schurman   private val classToInstanceMap = mutableMapOf<Class<*>, Any>()
54094c4dddSWill Schurman 
addnull55094c4dddSWill Schurman   fun add(clazz: Class<*>, instance: Any) {
56094c4dddSWill Schurman     classToInstanceMap[clazz] = instance
57094c4dddSWill Schurman   }
58094c4dddSWill Schurman 
injectnull59094c4dddSWill Schurman   fun inject(clazz: Class<*>, target: Any) {
60094c4dddSWill Schurman     for (field in clazz.declaredFields) {
61094c4dddSWill Schurman       injectFieldInTarget(target, field)
62094c4dddSWill Schurman     }
63094c4dddSWill Schurman   }
64094c4dddSWill Schurman 
injectFieldInTargetnull65094c4dddSWill Schurman   private fun injectFieldInTarget(target: Any, field: Field) {
66094c4dddSWill Schurman     if (field.isAnnotationPresent(Inject::class.java)) {
67094c4dddSWill Schurman       val fieldClazz = field.type
68094c4dddSWill Schurman       if (!classToInstanceMap.containsKey(fieldClazz)) {
69094c4dddSWill Schurman         throw RuntimeException("NativeModuleDepsProvider could not find object for class $fieldClazz")
70094c4dddSWill Schurman       }
71094c4dddSWill Schurman       val instance = classToInstanceMap[fieldClazz]
72094c4dddSWill Schurman       try {
73094c4dddSWill Schurman         field.isAccessible = true
74094c4dddSWill Schurman         field[target] = instance
75094c4dddSWill Schurman       } catch (e: IllegalAccessException) {
76094c4dddSWill Schurman         EXL.e(TAG, e.toString())
77094c4dddSWill Schurman       }
78094c4dddSWill Schurman     }
79094c4dddSWill Schurman   }
80094c4dddSWill Schurman 
81094c4dddSWill Schurman   companion object {
82094c4dddSWill Schurman     private val TAG = NativeModuleDepsProvider::class.java.simpleName
83094c4dddSWill Schurman 
84094c4dddSWill Schurman     @JvmStatic lateinit var instance: NativeModuleDepsProvider
85094c4dddSWill Schurman       private set
86094c4dddSWill Schurman 
87094c4dddSWill Schurman     private var useTestInstance = false
88094c4dddSWill Schurman 
initializenull89094c4dddSWill Schurman     fun initialize(application: Application) {
90094c4dddSWill Schurman       if (!useTestInstance) {
91094c4dddSWill Schurman         instance = NativeModuleDepsProvider(application)
92094c4dddSWill Schurman       }
93094c4dddSWill Schurman     }
94094c4dddSWill Schurman 
95094c4dddSWill Schurman     // Only for testing!
setTestInstancenull96094c4dddSWill Schurman     fun setTestInstance(instance: NativeModuleDepsProvider) {
97094c4dddSWill Schurman       Companion.instance = instance
98094c4dddSWill Schurman       useTestInstance = true
99094c4dddSWill Schurman     }
100094c4dddSWill Schurman   }
101094c4dddSWill Schurman 
102094c4dddSWill Schurman   init {
fieldnull103094c4dddSWill Schurman     for (field in NativeModuleDepsProvider::class.java.declaredFields) {
104094c4dddSWill Schurman       if (field.isAnnotationPresent(Inject::class.java)) {
105094c4dddSWill Schurman         try {
106094c4dddSWill Schurman           classToInstanceMap[field.type] = field[this]
107094c4dddSWill Schurman         } catch (e: IllegalAccessException) {
108094c4dddSWill Schurman           EXL.e(TAG, e.toString())
109094c4dddSWill Schurman         }
110094c4dddSWill Schurman       }
111094c4dddSWill Schurman     }
112094c4dddSWill Schurman   }
113094c4dddSWill Schurman }
114