<commit_before>/*
 * Copyright 2018 Google LLC
 *
 * 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
 *
 *     https://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.google.samples.apps.iosched.shared.data.userevent

import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MediatorLiveData
import android.arch.lifecycle.MutableLiveData
import android.support.annotation.WorkerThread
import com.google.samples.apps.iosched.shared.data.session.SessionRepository
import com.google.samples.apps.iosched.shared.domain.internal.DefaultScheduler
import com.google.samples.apps.iosched.shared.domain.sessions.LoadUserSessionUseCaseResult
import com.google.samples.apps.iosched.shared.domain.sessions.LoadUserSessionsByDayUseCaseResult
import com.google.samples.apps.iosched.shared.domain.users.ReservationRequestAction
import com.google.samples.apps.iosched.shared.domain.users.ReservationRequestAction.RequestAction
import com.google.samples.apps.iosched.shared.domain.users.ReservationRequestAction.SwapAction
import com.google.samples.apps.iosched.shared.domain.users.StarUpdatedStatus
import com.google.samples.apps.iosched.shared.domain.users.SwapRequestAction
import com.google.samples.apps.iosched.shared.domain.users.SwapRequestParameters
import com.google.samples.apps.iosched.shared.firestore.entity.UserEvent
import com.google.samples.apps.iosched.shared.model.Session
import com.google.samples.apps.iosched.shared.model.SessionId
import com.google.samples.apps.iosched.shared.model.UserSession
import com.google.samples.apps.iosched.shared.result.Result
import com.google.samples.apps.iosched.shared.util.TimeUtils.ConferenceDay
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Single point of access to user events data associated with a user for the presentation layer.
 */
@Singleton
open class DefaultSessionAndUserEventRepository @Inject constructor(
        private val userEventDataSource: UserEventDataSource,
        private val sessionRepository: SessionRepository
) : SessionAndUserEventRepository {

    private val sessionsByDayResult = MediatorLiveData<Result<LoadUserSessionsByDayUseCaseResult>>()

    // Keep a reference to the observable for a single event (from the details screen) so we can
    // stop observing when done.
    private var observableUserEvent: LiveData<UserEventResult>? = null

    override fun getObservableUserEvents(userId: String?):
            LiveData<Result<LoadUserSessionsByDayUseCaseResult>> {

        // If there is no logged-in user, return the map with null UserEvents
        if (userId == null) {
            Timber.d("EventRepository: No user logged in, returning sessions without user events.")
            val allSessions = sessionRepository.getSessions()
            val userSessionsPerDay = mapUserDataAndSessions(null, allSessions)
            sessionsByDayResult.postValue(Result.Success(
                LoadUserSessionsByDayUseCaseResult(
                    userSessionsPerDay = userSessionsPerDay,
                    userMessage = null,
                    userSessionCount = allSessions.size)
            ))
            return sessionsByDayResult
        }
        // Observes the user events and merges them with session data.
        val observableUserEvents = userEventDataSource.getObservableUserEvents(userId)
        sessionsByDayResult.removeSource(observableUserEvents)
        sessionsByDayResult.addSource(observableUserEvents) { userEvents ->
            DefaultScheduler.execute {
                try {
                    Timber.d("EventRepository: Received " +
                            "${userEvents?.userEvents?.size ?: 0} user events changes")

                    // Get the sessions, synchronously
                    val allSessions = sessionRepository.getSessions()

                    // Merges sessions with user data and emits the result
                    val userEventsMessageSession = allSessions.firstOrNull {
                        it.id == userEvents?.userEventsMessage?.sessionId
                    }
                    sessionsByDayResult.postValue(Result.Success(
                        LoadUserSessionsByDayUseCaseResult(
                            userSessionsPerDay = mapUserDataAndSessions(
                                userEvents, allSessions),
                            userMessage = userEvents?.userEventsMessage,
                            userMessageSession = userEventsMessageSession,
                            userSessionCount = allSessions.size)
                    ))

                } catch (e: Exception) {
                    sessionsByDayResult.postValue(Result.Error(e))
                }
            }
        }
        return sessionsByDayResult
    }

    override fun getObservableUserEvent(
            userId: String?,
            eventId: SessionId
    ): LiveData<Result<LoadUserSessionUseCaseResult>> {
        val sessionResult = MediatorLiveData<Result<LoadUserSessionUseCaseResult>>()

        // If there is no logged-in user, return the session with a null UserEvent
        if (userId == null) {
            Timber.d("EventRepository: No user logged in, returning session without user event.")
            val session = sessionRepository.getSession(eventId)
            sessionResult.postValue(Result.Success(
                    LoadUserSessionUseCaseResult(
                            userSession = UserSession(session, createDefaultUserEvent(session)),
                            userMessage = null)
            ))
            return sessionResult
        }

        // Observes the user events and merges them with session data.<commit_msg>Fix the blur when toggling the pinned events switch<commit_after>/*
 * Copyright 2018 Google LLC
 *
 * 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
 *
 *     https://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.google.samples.apps.iosched.shared.data.userevent

import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MediatorLiveData
import android.arch.lifecycle.MutableLiveData
import android.support.annotation.WorkerThread
import com.google.samples.apps.iosched.shared.data.session.SessionRepository
import com.google.samples.apps.iosched.shared.domain.internal.DefaultScheduler
import com.google.samples.apps.iosched.shared.domain.sessions.LoadUserSessionUseCaseResult
import com.google.samples.apps.iosched.shared.domain.sessions.LoadUserSessionsByDayUseCaseResult
import com.google.samples.apps.iosched.shared.domain.users.ReservationRequestAction
import com.google.samples.apps.iosched.shared.domain.users.ReservationRequestAction.RequestAction
import com.google.samples.apps.iosched.shared.domain.users.ReservationRequestAction.SwapAction
import com.google.samples.apps.iosched.shared.domain.users.StarUpdatedStatus
import com.google.samples.apps.iosched.shared.domain.users.SwapRequestAction
import com.google.samples.apps.iosched.shared.domain.users.SwapRequestParameters
import com.google.samples.apps.iosched.shared.firestore.entity.UserEvent
import com.google.samples.apps.iosched.shared.model.Session
import com.google.samples.apps.iosched.shared.model.SessionId
import com.google.samples.apps.iosched.shared.model.UserSession
import com.google.samples.apps.iosched.shared.result.Result
import com.google.samples.apps.iosched.shared.util.TimeUtils.ConferenceDay
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Single point of access to user events data associated with a user for the presentation layer.
 */
@Singleton
open class DefaultSessionAndUserEventRepository @Inject constructor(
        private val userEventDataSource: UserEventDataSource,
        private val sessionRepository: SessionRepository
) : SessionAndUserEventRepository {

    private val sessionsByDayResult = MediatorLiveData<Result<LoadUserSessionsByDayUseCaseResult>>()

    // Keep a reference to the observable for a single event (from the details screen) so we can
    // stop observing when done.
    private var observableUserEvent: LiveData<UserEventResult>? = null

    override fun getObservableUserEvents(userId: String?):
            LiveData<Result<LoadUserSessionsByDayUseCaseResult>> {

        // If there is no logged-in user, return the map with null UserEvents
        if (userId == null) {
            Timber.d("EventRepository: No user logged in, returning sessions without user events.")
            val allSessions = sessionRepository.getSessions()
            val userSessionsPerDay = mapUserDataAndSessions(null, allSessions)
            sessionsByDayResult.postValue(Result.Success(
                LoadUserSessionsByDayUseCaseResult(
                    userSessionsPerDay = userSessionsPerDay,
                    userMessage = null,
                    userSessionCount = allSessions.size)
            ))
            return sessionsByDayResult
        }
        // Observes the user events and merges them with session data.
        val observableUserEvents = userEventDataSource.getObservableUserEvents(userId)
        sessionsByDayResult.removeSource(observableUserEvents)
        sessionsByDayResult.addSource(observableUserEvents) { userEvents ->
            DefaultScheduler.execute {
                try {
                    // Not update the result when userEvents is null, otherwise the count of the
                    // filtered result in the use case is going to be 0, that results blur when
                    // the pinned item switch is toggled.
                    userEvents ?: return@execute

                    Timber.d(
                        """EventRepository: Received ${userEvents.userEvents.size}
                            |user events changes""".trimMargin()
                    )

                    // Get the sessions, synchronously
                    val allSessions = sessionRepository.getSessions()

                    // Merges sessions with user data and emits the result
                    val userEventsMessageSession = allSessions.firstOrNull {
                        it.id == userEvents.userEventsMessage?.sessionId
                    }
                    sessionsByDayResult.postValue(Result.Success(
                        LoadUserSessionsByDayUseCaseResult(
                            userSessionsPerDay = mapUserDataAndSessions(
                                userEvents, allSessions),
                            userMessage = userEvents.userEventsMessage,
                            userMessageSession = userEventsMessageSession,
                            userSessionCount = allSessions.size)
                    ))

                } catch (e: Exception) {
                    sessionsByDayResult.postValue(Result.Error(e))
                }
            }
        }
        return sessionsByDayResult
    }

    override fun getObservableUserEvent(
            userId: String?,
            eventId: SessionId
    ): LiveData<Result<LoadUserSessionUseCaseResult>> {
        val sessionResult = MediatorLiveData<Result<LoadUserSessionUseCaseResult>>()

        // If there is no logged-in user, return the session with a null UserEvent
        if (userId == null) {
            Timber.d("EventRepository: No user logged in, returning session without user event.")
            val session = sessionRepository.getSession(eventId)
            sessionResult.postValue(Result.Success(
                    LoadUserSessionUseCaseResult(
                            userSession = UserSession(session, createDefaultUserEvent(session)),
                            userMessage = null)
            ))
            return sessionResult
        }

        // Observes the user events and merges them with session data.
{'fraction_non_alphanumeric': 0.06953143582018552, 'fraction_numerical': 0.0014270990248156665, 'mean_word_length': 2.6477732793522266, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 23, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, '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': '2660033', 'n_tokens_mistral': 3083, 'n_tokens_neox': 3015, 'n_words': 767}