package be.simplenotes.app.api import be.simplenotes.app.extensions.auto import be.simplenotes.app.utils.parseSearchTerms import be.simplenotes.domain.usecases.NoteService import be.simplenotes.types.LoggedInUser import be.simplenotes.types.PersistedNote import be.simplenotes.types.PersistedNoteMetadata import kotlinx.serialization.Contextual import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import org.http4k.core.Request import org.http4k.core.Response import org.http4k.core.Status.Companion.BAD_REQUEST import org.http4k.core.Status.Companion.NOT_FOUND import org.http4k.core.Status.Companion.OK import org.http4k.lens.Path import org.http4k.lens.uuid import java.util.* import javax.inject.Singleton @Singleton class ApiNoteController( json: Json, private val noteService: NoteService, ) { fun createNote(request: Request, loggedInUser: LoggedInUser): Response { val content = noteContentLens(request) return noteService.create(loggedInUser.userId, content).fold( { Response(BAD_REQUEST) }, { uuidContentLens(UuidContent(it.uuid), Response(OK)) } ) } fun notes(@Suppress("UNUSED_PARAMETER") request: Request, loggedInUser: LoggedInUser): Response { val notes = noteService.paginatedNotes(loggedInUser.userId, page = 1).notes return persistedNotesMetadataLens(notes, Response(OK)) } fun note(request: Request, loggedInUser: LoggedInUser): Response = noteService.find(loggedInUser.userId, uuidLens(request)) ?.let { persistedNoteLens(it, Response(OK)) } ?: Response(NOT_FOUND) fun update(request: Request, loggedInUser: LoggedInUser): Response { val content = noteContentLens(request) return noteService.update(loggedInUser.userId, uuidLens(request), content).fold( { Response(BAD_REQUEST) }, { if (it == null) Response(NOT_FOUND) else Response(OK) } ) } fun search(request: Request, loggedInUser: LoggedInUser): Response { val query = searchContentLens(request) val terms = parseSearchTerms(query) val notes = noteService.search(loggedInUser.userId, terms) return persistedNotesMetadataLens(notes, Response(OK)) } private val uuidContentLens = json.auto().toLens() private val noteContentLens = json.auto().map { it.content }.toLens() private val searchContentLens = json.auto().map { it.query }.toLens() private val persistedNotesMetadataLens = json.auto>().toLens() private val persistedNoteLens = json.auto().toLens() private val uuidLens = Path.uuid().of("uuid") } @Serializable data class NoteContent(val content: String) @Serializable data class UuidContent(@Contextual val uuid: UUID) @Serializable data class SearchContent(@Contextual val query: String)