package de.sebse.fuplanner2.database

import android.content.Context
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.sqlite.db.SupportSQLiteDatabase


@Database(
    entities = [
        User::class, Course::class, Cache::class,
        Notification::class, Event::class, Announcement::class
    ],
    version = 1
)
@TypeConverters(Converters::class)
abstract class AppDatabase: RoomDatabase() {
    abstract fun userDao(): UserDao
    abstract fun courseDao(): CourseDao
    abstract fun cacheDao(): CacheDao
    abstract fun notificationDao(): NotificationDao
    abstract fun eventDao(): EventDao
    abstract fun announcementDao(): AnnouncementDao

    private val mIsDatabaseCreated = MutableLiveData<Boolean>()

    companion object {
        @VisibleForTesting
        val DATABASE_NAME = "app-db"

        private var sInstance: AppDatabase? = null

        fun initialize(context: Context): AppDatabase? {
            if (sInstance == null) {
                synchronized(AppDatabase::class.java) {
                    if (sInstance == null) {
                        sInstance = buildDatabase(context.applicationContext)
                        sInstance?.updateDatabaseCreated(context.applicationContext)
                    }
                }
            }
            return sInstance
        }

        fun getInstance(): AppDatabase {
            sInstance?.let {
                return it
            }
            throw NullPointerException("Please call initialize() before getting the instance.")
        }

        private fun buildDatabase(
            appContext: Context
        ): AppDatabase {
            return Room.databaseBuilder(appContext, AppDatabase::class.java, DATABASE_NAME)
                .addCallback(object : Callback() {
                    override fun onCreate(db: SupportSQLiteDatabase) {
                        super.onCreate(db)
                        val database = getInstance()
                        database.setDatabaseCreated()
                    }
                }).build()
        }
    }

    private fun updateDatabaseCreated(context: Context) {
        if (context.getDatabasePath(DATABASE_NAME).exists()) {
            setDatabaseCreated()
        }
    }

    private fun setDatabaseCreated() {
        mIsDatabaseCreated.postValue(true)
    }

    fun getDatabaseCreated(): LiveData<Boolean?> {
        return mIsDatabaseCreated
    }
}