From 8686e60fbc02a01f67721180d7ad406132482c58 Mon Sep 17 00:00:00 2001
From: InsanusMokrassar <ovsyannikov.alexey95@gmail.com>
Date: Wed, 5 Aug 2020 00:23:30 +0600
Subject: [PATCH] temporal update of markups system

---
 .../postssystem/markups/core/MarkupPlugin.kt  | 26 ++++------
 .../postssystem/markups/core/MarkupsSystem.kt | 47 +++++++++++++++++++
 .../markups/core/utils/ListBuilder.kt         | 18 +++++++
 .../utils/repos/StandardCRUDRepo.kt           |  9 ++--
 .../utils/repos/pagination/Pagination.kt      | 11 ++++-
 5 files changed, 87 insertions(+), 24 deletions(-)
 create mode 100644 postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/MarkupsSystem.kt
 create mode 100644 postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/utils/ListBuilder.kt

diff --git a/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/MarkupPlugin.kt b/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/MarkupPlugin.kt
index 4132cf62..9e3833fd 100644
--- a/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/MarkupPlugin.kt
+++ b/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/MarkupPlugin.kt
@@ -2,34 +2,26 @@ package com.insanusmokrassar.postssystem.markups.core
 
 import com.insanusmokrassar.postssystem.core.post.PostId
 
+typealias MarkupPluginName = String
+typealias MarkupPluginIdentifier = String
+
 /**
  * That is the plugin for platform, which is able to be drawn on the [MarkupTarget].
  *
  * * Plugin could be some Telegram plugin
  * * [MarkupTarget] could be web.
  */
-interface MarkupPlugin<MarkupTarget> {
+interface MarkupPlugin {
     /**
      * This name will be used in `select`-questions on site
      */
-    val name: String
+    val pluginName: MarkupPluginName
+
+    val pluginId: MarkupPluginIdentifier
+        get() = pluginName
 
     /**
      * Link to icon which will be used for links onto this plugin
      */
     val iconLink: String?
-
-    /**
-     * Drawing on [MarkupTarget].
-     *
-     * As a result, plugin must use [MarkupTarget] as a canvas to create the builder of markup. This fun
-     * will be implemented by creators like:
-     *
-     * * Telegram
-     * * Web
-     * * etc.
-     *
-     * For example, it could be some creator like "TelegramForHTMLMarkupBuilder"
-     */
-    suspend fun drawMarkupBuilder(on: MarkupTarget, postId: PostId)
-}
\ No newline at end of file
+}
diff --git a/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/MarkupsSystem.kt b/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/MarkupsSystem.kt
new file mode 100644
index 00000000..2d50b338
--- /dev/null
+++ b/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/MarkupsSystem.kt
@@ -0,0 +1,47 @@
+package com.insanusmokrassar.postssystem.markups.core
+
+import com.insanusmokrassar.postssystem.markups.core.utils.*
+import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
+import com.insanusmokrassar.postssystem.utils.repos.pagination.*
+import kotlin.math.min
+
+abstract class MarkupsSystem(
+    protected val plugins: List<MarkupPlugin>
+) : ReadStandardCRUDRepo<MarkupPlugin, MarkupPluginIdentifier> {
+    private val pluginsMap: Map<MarkupPluginIdentifier, MarkupPlugin> = plugins.associateBy { it.pluginId }
+
+    override suspend fun contains(id: MarkupPluginIdentifier): Boolean = pluginsMap.keys.contains(id)
+    override suspend fun getById(id: MarkupPluginIdentifier): MarkupPlugin? = pluginsMap[id]
+    override suspend fun getByPagination(pagination: Pagination): PaginationResult<MarkupPlugin> {
+        if (pagination.firstIndex > plugins.lastIndex) {
+            return emptyList<MarkupPlugin>().createPaginationResult(
+                pagination,
+                plugins.size.toLong()
+            )
+        }
+        val lastExclusiveIndex = min(pagination.lastExclusiveIndex, plugins.size)
+        return plugins.subList(pagination.firstIndex, lastExclusiveIndex).createPaginationResult(
+            pagination,
+            plugins.size.toLong()
+        )
+    }
+
+    fun drawPluginsNamedList(
+        listBuilder: ListBuilder
+    ) {
+        listBuilder.createLinkedItems(
+            plugins.map {
+                it.pluginName to it.pluginId
+            }
+        )
+    }
+    fun drawPluginsIconsList(
+        listBuilder: ListBuilder
+    ) {
+        listBuilder.createLinkedIconItems(
+            plugins.mapNotNull {
+                (it.iconLink ?: return@mapNotNull null) to it.pluginId
+            }
+        )
+    }
+}
diff --git a/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/utils/ListBuilder.kt b/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/utils/ListBuilder.kt
new file mode 100644
index 00000000..962fd2a8
--- /dev/null
+++ b/postssystem.markups.core/src/commonMain/kotlin/com/insanusmokrassar/postssystem/markups/core/utils/ListBuilder.kt
@@ -0,0 +1,18 @@
+package com.insanusmokrassar.postssystem.markups.core.utils
+
+import com.insanusmokrassar.postssystem.markups.core.MarkupPluginIdentifier
+import com.insanusmokrassar.postssystem.markups.core.MarkupPluginName
+
+typealias TitledListItem = Pair<MarkupPluginName, MarkupPluginIdentifier>
+typealias IconLinkListItem = Pair<String, MarkupPluginIdentifier>
+
+interface ListBuilder {
+    /**
+     * Accept the list of titled items with their ids
+     */
+    fun createLinkedItems(data: List<TitledListItem>)
+    /**
+     * Accept the list of items with their icons links and ids
+     */
+    fun createLinkedIconItems(data: List<IconLinkListItem>)
+}
diff --git a/postssystem.utils.repos/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/StandardCRUDRepo.kt b/postssystem.utils.repos/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/StandardCRUDRepo.kt
index 1a657078..dd57961d 100644
--- a/postssystem.utils.repos/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/StandardCRUDRepo.kt
+++ b/postssystem.utils.repos/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/StandardCRUDRepo.kt
@@ -4,8 +4,7 @@ import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination
 import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult
 import kotlinx.coroutines.flow.Flow
 
-interface ReadStandardCRUDRepo<ObjectType, IdType> :
-    Repo {
+interface ReadStandardCRUDRepo<ObjectType, IdType> : Repo {
     suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType>
     suspend fun getById(id: IdType): ObjectType?
     suspend fun contains(id: IdType): Boolean
@@ -17,8 +16,7 @@ val <IdType> UpdatedValuePair<IdType, *>.id
 val <ValueType> UpdatedValuePair<*, ValueType>.value
     get() = second
 
-interface WriteStandardCRUDRepo<ObjectType, IdType, InputValueType> :
-    Repo {
+interface WriteStandardCRUDRepo<ObjectType, IdType, InputValueType> : Repo {
     val newObjectsFlow: Flow<ObjectType>
     val updatedObjectsFlow: Flow<ObjectType>
     val deletedObjectsIdsFlow: Flow<IdType>
@@ -29,6 +27,5 @@ interface WriteStandardCRUDRepo<ObjectType, IdType, InputValueType> :
     suspend fun deleteById(vararg ids: IdType)
 }
 
-interface StandardCRUDRepo<ObjectType, IdType, InputValueType>
-    : ReadStandardCRUDRepo<ObjectType, IdType>,
+interface StandardCRUDRepo<ObjectType, IdType, InputValueType> : ReadStandardCRUDRepo<ObjectType, IdType>,
     WriteStandardCRUDRepo<ObjectType, IdType, InputValueType>
diff --git a/postssystem.utils.repos/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/pagination/Pagination.kt b/postssystem.utils.repos/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/pagination/Pagination.kt
index 1045624c..83164816 100644
--- a/postssystem.utils.repos/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/pagination/Pagination.kt
+++ b/postssystem.utils.repos/src/commonMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/pagination/Pagination.kt
@@ -27,6 +27,15 @@ interface Pagination {
 val Pagination.firstIndex: Int
     get() = page * size
 
+/**
+ * Last exclusive number in index of objects
+ *
+ * For [Pagination] with [Pagination.size] == 10 and [Pagination.page] == 1
+ * you will retrieve [Pagination.firstIndex] == 10 and [Pagination.lastExclusiveIndex] == 20.
+ */
+val Pagination.lastExclusiveIndex: Int
+    get() = firstIndex + size
+
 /**
  * Last number in index of objects. In fact, one [Pagination] object represent data in next range:
  *
@@ -34,7 +43,7 @@ val Pagination.firstIndex: Int
  * you will retrieve [Pagination.firstIndex] == 10 and [Pagination.lastIndex] == 19.
  */
 val Pagination.lastIndex: Int
-    get() = firstIndex + size - 1
+    get() = lastExclusiveIndex - 1
 
 /**
  * Calculates pages count for given [datasetSize]