diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt
index a8f6b2e67fcc6907b3e5c8d844972ce9395488fe..d270cc5c8091707720b01fcfaeecfb8af198f8cb 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt
@@ -14,8 +14,8 @@ import de.kuschku.quasseldroid_ng.R
 import de.kuschku.quasseldroid_ng.persistence.AccountDatabase
 import de.kuschku.quasseldroid_ng.persistence.QuasselBacklogStorage
 import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
-import de.kuschku.quasseldroid_ng.ui.settings.data.ConnectionSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.Settings
+import de.kuschku.quasseldroid_ng.settings.ConnectionSettings
+import de.kuschku.quasseldroid_ng.settings.Settings
 import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread
 import de.kuschku.quasseldroid_ng.util.QuasseldroidNotificationManager
 import de.kuschku.quasseldroid_ng.util.compatibility.AndroidHandlerService
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/settings/AppearanceSettings.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/settings/AppearanceSettings.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b0b4e5f00424178671b81f53f7befa9db0e6f95d
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/settings/AppearanceSettings.kt
@@ -0,0 +1,69 @@
+package de.kuschku.quasseldroid_ng.settings
+
+import android.support.annotation.StyleRes
+import de.kuschku.quasseldroid_ng.R
+
+data class AppearanceSettings(
+  val showPrefix: ShowPrefixMode = ShowPrefixMode.HIGHEST,
+  val colorizeNicknames: ColorizeNicknamesMode = ColorizeNicknamesMode.ALL_BUT_MINE,
+  val inputEnter: InputEnterMode = InputEnterMode.EMOJI,
+  val colorizeMirc: Boolean = true,
+  val useMonospace: Boolean = false,
+  val showSeconds: Boolean = false,
+  val use24hClock: Boolean = true,
+  val showAutocomplete: Boolean = true,
+  val showHostmask: Boolean = false,
+  val showLag: Boolean = true,
+  val theme: Theme = Theme.QUASSEL_LIGHT
+) {
+  enum class ColorizeNicknamesMode {
+    ALL,
+    ALL_BUT_MINE,
+    NONE;
+
+    companion object {
+      private val map = values().associateBy { it.name }
+      fun of(name: String) = map[name]
+    }
+  }
+
+  enum class InputEnterMode {
+    EMOJI,
+    SEND;
+
+    companion object {
+      private val map = values().associateBy { it.name }
+      fun of(name: String) = map[name]
+    }
+  }
+
+  enum class ShowPrefixMode {
+    ALL,
+    HIGHEST,
+    NONE;
+
+    companion object {
+      private val map = values().associateBy { it.name }
+      fun of(name: String) = map[name]
+    }
+  }
+
+  enum class Theme(@StyleRes val style: Int) {
+    QUASSEL_LIGHT(R.style.Theme_ChatTheme_Quassel_Light),
+    QUASSEL_DARK(R.style.Theme_ChatTheme_Quassel_Dark),
+    AMOLED(R.style.Theme_ChatTheme_Amoled),
+    SOLARIZED_LIGHT(R.style.Theme_ChatTheme_Solarized_Light),
+    SOLARIZED_DARK(R.style.Theme_ChatTheme_Solarized_Dark),
+    GRUVBOX_LIGHT(R.style.Theme_ChatTheme_Gruvbox_Light),
+    GRUVBOX_DARK(R.style.Theme_ChatTheme_Gruvbox_Dark);
+
+    companion object {
+      private val map = values().associateBy { it.name }
+      fun of(name: String) = map[name]
+    }
+  }
+
+  companion object {
+    val DEFAULT = AppearanceSettings()
+  }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/settings/BacklogSettings.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/settings/BacklogSettings.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c15f4e463b683e5a69fdfbe222b5bbfb19a724fc
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/settings/BacklogSettings.kt
@@ -0,0 +1,9 @@
+package de.kuschku.quasseldroid_ng.settings
+
+data class BacklogSettings(
+  val dynamicAmount: Int = 20
+) {
+  companion object {
+    val DEFAULT = BacklogSettings()
+  }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/settings/ConnectionSettings.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/settings/ConnectionSettings.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ad0e5993bd8ecbd1df53bfc23655d2dbcc680376
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/settings/ConnectionSettings.kt
@@ -0,0 +1,9 @@
+package de.kuschku.quasseldroid_ng.settings
+
+data class ConnectionSettings(
+  val showNotification: Boolean = true
+) {
+  companion object {
+    val DEFAULT = ConnectionSettings()
+  }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/settings/Settings.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/settings/Settings.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f78f23cd82ccff4fc710d8de8531db38b70fdea1
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/settings/Settings.kt
@@ -0,0 +1,83 @@
+package de.kuschku.quasseldroid_ng.settings
+
+import android.content.Context
+import de.kuschku.quasseldroid_ng.R
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings.*
+import de.kuschku.quasseldroid_ng.util.helper.sharedPreferences
+
+object Settings {
+  fun appearance(context: Context) = context.sharedPreferences {
+    AppearanceSettings(
+      theme = Theme.of(
+        getString(
+          context.getString(R.string.preference_theme_key),
+          ""
+        )
+      ) ?: AppearanceSettings.DEFAULT.theme,
+      useMonospace = getBoolean(
+        context.getString(R.string.preference_monospace_key),
+        AppearanceSettings.DEFAULT.useMonospace
+      ),
+      showSeconds = getBoolean(
+        context.getString(R.string.preference_show_seconds_key),
+        AppearanceSettings.DEFAULT.showSeconds
+      ),
+      use24hClock = getBoolean(
+        context.getString(R.string.preference_use_24h_clock_key),
+        AppearanceSettings.DEFAULT.use24hClock
+      ),
+      showPrefix = ShowPrefixMode.of(
+        getString(
+          context.getString(R.string.preference_show_prefix_key),
+          ""
+        )
+      ) ?: AppearanceSettings.DEFAULT.showPrefix,
+      colorizeNicknames = ColorizeNicknamesMode.of(
+        getString(
+          context.getString(R.string.preference_colorize_nicknames_key),
+          ""
+        )
+      ) ?: AppearanceSettings.DEFAULT.colorizeNicknames,
+      inputEnter = InputEnterMode.of(
+        getString(
+          context.getString(R.string.preference_input_enter_key),
+          ""
+        )
+      ) ?: AppearanceSettings.DEFAULT.inputEnter,
+      colorizeMirc = getBoolean(
+        context.getString(R.string.preference_colorize_mirc_key),
+        AppearanceSettings.DEFAULT.colorizeMirc
+      ),
+      showAutocomplete = getBoolean(
+        context.getString(R.string.preference_autocomplete_key),
+        AppearanceSettings.DEFAULT.showAutocomplete
+      ),
+      showHostmask = getBoolean(
+        context.getString(R.string.preference_hostmask_key),
+        AppearanceSettings.DEFAULT.showHostmask
+      ),
+      showLag = getBoolean(
+        context.getString(R.string.preference_show_lag_key),
+        AppearanceSettings.DEFAULT.showLag
+      )
+    )
+  }
+
+  fun backlog(context: Context) = context.sharedPreferences {
+    BacklogSettings(
+      dynamicAmount = getString(
+        context.getString(R.string.preference_dynamic_fetch_key),
+        BacklogSettings.DEFAULT.dynamicAmount.toString()
+      ).toIntOrNull() ?: BacklogSettings.DEFAULT.dynamicAmount
+    )
+  }
+
+  fun connection(context: Context) = context.sharedPreferences {
+    ConnectionSettings(
+      showNotification = getBoolean(
+        context.getString(R.string.preference_show_notification_key),
+        ConnectionSettings.DEFAULT.showNotification
+      )
+    )
+  }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/AutoCompleteAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/AutoCompleteAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7779e26f4b2d1392414573ed4e7bc300d42b4a52
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/AutoCompleteAdapter.kt
@@ -0,0 +1,121 @@
+package de.kuschku.quasseldroid_ng.ui.chat
+
+import android.arch.lifecycle.LifecycleOwner
+import android.arch.lifecycle.LiveData
+import android.arch.lifecycle.Observer
+import android.support.v7.util.DiffUtil
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import butterknife.BindView
+import butterknife.ButterKnife
+import de.kuschku.quasseldroid_ng.R
+import de.kuschku.quasseldroid_ng.util.helper.visibleIf
+import de.kuschku.quasseldroid_ng.util.irc.IrcCaseMappers
+
+class AutoCompleteAdapter(
+  lifecycleOwner: LifecycleOwner,
+  liveData: LiveData<List<NickListAdapter.IrcUserItem>?>,
+  runInBackground: (() -> Unit) -> Any,
+  runOnUiThread: (Runnable) -> Any,
+  private val clickListener: ((String) -> Unit)? = null
+) : RecyclerView.Adapter<AutoCompleteAdapter.NickViewHolder>() {
+  var data = mutableListOf<NickListAdapter.IrcUserItem>()
+
+  init {
+    liveData.observe(
+      lifecycleOwner, Observer { it: List<NickListAdapter.IrcUserItem>? ->
+      runInBackground {
+        val list = it ?: emptyList()
+        val old: List<NickListAdapter.IrcUserItem> = data
+        val new: List<NickListAdapter.IrcUserItem> = list
+          .sortedBy { IrcCaseMappers[it.networkCasemapping].toLowerCase(it.nick) }
+          .sortedBy { it.lowestMode }
+        val result = DiffUtil.calculateDiff(
+          object : DiffUtil.Callback() {
+            override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
+              old[oldItemPosition].nick == new[newItemPosition].nick
+
+            override fun getOldListSize() = old.size
+            override fun getNewListSize() = new.size
+            override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
+              old[oldItemPosition] == new[newItemPosition]
+          }, true
+        )
+        runOnUiThread(
+          Runnable {
+            data.clear()
+            data.addAll(new)
+            result.dispatchUpdatesTo(this@AutoCompleteAdapter)
+          }
+        )
+      }
+    }
+    )
+  }
+
+  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = NickViewHolder(
+    LayoutInflater.from(parent.context).inflate(
+      when (viewType) {
+        VIEWTYPE_AWAY -> R.layout.widget_nick_away
+        else          -> R.layout.widget_nick
+      }, parent, false
+    ),
+    clickListener = clickListener
+  )
+
+  override fun onBindViewHolder(holder: NickViewHolder, position: Int) = holder.bind(data[position])
+
+  override fun getItemCount() = data.size
+
+  override fun getItemViewType(position: Int) = if (data[position].away) {
+    VIEWTYPE_AWAY
+  } else {
+    VIEWTYPE_ACTIVE
+  }
+
+  class NickViewHolder(
+    itemView: View,
+    private val clickListener: ((String) -> Unit)? = null
+  ) : RecyclerView.ViewHolder(itemView) {
+    @BindView(R.id.modesContainer)
+    lateinit var modesContainer: View
+
+    @BindView(R.id.modes)
+    lateinit var modes: TextView
+
+    @BindView(R.id.nick)
+    lateinit var nick: TextView
+
+    @BindView(R.id.realname)
+    lateinit var realname: TextView
+
+    var user: String? = null
+
+    init {
+      ButterKnife.bind(this, itemView)
+      itemView.setOnClickListener {
+        val nick = user
+        if (nick != null)
+          clickListener?.invoke(nick)
+      }
+    }
+
+    fun bind(data: NickListAdapter.IrcUserItem) {
+      user = data.nick
+
+      nick.text = data.nick
+      modes.text = data.modes
+      realname.text = data.realname
+
+      modes.visibleIf(data.modes.isNotBlank())
+    }
+  }
+
+  companion object {
+    val VIEWTYPE_ACTIVE = 0
+    val VIEWTYPE_AWAY = 1
+  }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt
index af0bf9cb1cff0e9c3b3d942aa8f150edcfdce917..76291f6fd5471a7782110a67ee7438bacf650722 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt
@@ -14,9 +14,10 @@ import android.support.design.widget.Snackbar
 import android.support.v4.graphics.drawable.DrawableCompat
 import android.support.v4.widget.DrawerLayout
 import android.support.v7.app.ActionBarDrawerToggle
-import android.support.v7.widget.ActionMenuView
-import android.support.v7.widget.Toolbar
+import android.support.v7.widget.*
+import android.text.Editable
 import android.text.InputType
+import android.text.TextWatcher
 import android.view.*
 import android.view.inputmethod.EditorInfo
 import android.widget.EditText
@@ -34,15 +35,17 @@ import de.kuschku.libquassel.util.or
 import de.kuschku.quasseldroid_ng.Keys
 import de.kuschku.quasseldroid_ng.R
 import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings
+import de.kuschku.quasseldroid_ng.settings.BacklogSettings
+import de.kuschku.quasseldroid_ng.settings.Settings
 import de.kuschku.quasseldroid_ng.ui.settings.SettingsActivity
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.BacklogSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.Settings
 import de.kuschku.quasseldroid_ng.ui.viewmodel.QuasselViewModel
 import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread
 import de.kuschku.quasseldroid_ng.util.helper.*
 import de.kuschku.quasseldroid_ng.util.service.ServiceBoundActivity
 import de.kuschku.quasseldroid_ng.util.ui.MaterialContentLoadingProgressBar
+import io.reactivex.subjects.BehaviorSubject
+import java.util.concurrent.TimeUnit
 
 class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenceChangeListener,
                      ActionMenuView.OnMenuItemClickListener {
@@ -70,6 +73,12 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
   @BindView(R.id.chatline)
   lateinit var chatline: EditText
 
+  @BindView(R.id.autocomplete_list)
+  lateinit var autocompleteList: RecyclerView
+
+  @BindView(R.id.autocomplete_list2)
+  lateinit var autocompleteList2: RecyclerView
+
   private lateinit var drawerToggle: ActionBarDrawerToggle
 
   private val handler = AndroidHandlerThread("Chat")
@@ -105,6 +114,15 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
     }
   }
 
+  private val lastWord = BehaviorSubject.createDefault("")
+  private val textWatcher = object : TextWatcher {
+    override fun afterTextChanged(s: Editable?) =
+      lastWord.onNext(s?.lastWord(chatline.selectionStart, onlyBeforeCursor = true).toString())
+
+    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
+    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
+  }
+
   override fun onCreate(savedInstanceState: Bundle?) {
     handler.onCreate()
     super.onCreate(savedInstanceState)
@@ -192,6 +210,40 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc
       }
     })
 
+    val autocompleteAdapter = AutoCompleteAdapter(
+      this,
+      viewModel.nickData.switchMapRx { nicks ->
+        lastWord
+          .filter { it.length >= 3 || it.isEmpty() }
+          .distinctUntilChanged()
+          .debounce(100, TimeUnit.MILLISECONDS)
+          .map { input ->
+            if (input.isEmpty()) {
+              emptyList()
+            } else {
+              nicks.filter {
+                it.nick.contains(input, ignoreCase = true)
+              }.sortedBy(NickListAdapter.IrcUserItem::nick)
+            }
+          }
+      },
+      handler::post,
+      ::runOnUiThread,
+      inputEditor::autoComplete
+    )
+
+    if (appearanceSettings.showAutocomplete) {
+      autocompleteList.layoutManager = LinearLayoutManager(this)
+      autocompleteList.itemAnimator = DefaultItemAnimator()
+      autocompleteList.adapter = autocompleteAdapter
+
+      autocompleteList2.layoutManager = LinearLayoutManager(this)
+      autocompleteList2.itemAnimator = DefaultItemAnimator()
+      autocompleteList2.adapter = autocompleteAdapter
+    }
+
+    chatline.addTextChangedListener(textWatcher)
+
     editorPanel.addPanelSlideListener(panelSlideListener)
     editorPanel.panelState = SlidingUpPanelLayout.PanelState.COLLAPSED
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/InputEditor.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/InputEditor.kt
index ebf820700774b0bee95470d080ff859dfbc52130..d096c6aa9f31c2d25baf80d8b1b0e56de53557eb 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/InputEditor.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/InputEditor.kt
@@ -204,4 +204,19 @@ class InputEditor(private val editText: EditText) {
 
     return removedAny
   }
+
+  fun autoComplete(text: CharSequence) {
+    val beginningOfWord = editText.text.lastIndexOf(' ', editText.selectionStart)
+    val endOfWord = editText.text.indexOf(' ', editText.selectionEnd)
+    val start = beginningOfWord + 1
+    val end = if (endOfWord != -1) {
+      endOfWord
+    } else {
+      editText.text.length
+    }
+
+    val replacement = "$text: "
+    editText.text.replace(start, end, replacement)
+    editText.setSelection(start + replacement.length)
+  }
 }
\ No newline at end of file
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListFragment.kt
index 0590152f924b1042ba93c9f38541a8adbe5edaf5..5ff1deaa63b5a14f26818c1659bfaf284beefa41 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/NickListFragment.kt
@@ -11,8 +11,8 @@ import android.view.ViewGroup
 import butterknife.BindView
 import butterknife.ButterKnife
 import de.kuschku.quasseldroid_ng.R
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.Settings
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings
+import de.kuschku.quasseldroid_ng.settings.Settings
 import de.kuschku.quasseldroid_ng.ui.viewmodel.QuasselViewModel
 import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread
 import de.kuschku.quasseldroid_ng.util.helper.map
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ToolbarFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ToolbarFragment.kt
index 57d9802b2ffd09d06ced95fcee358343172ebce2..207c933b878bd1162a33f0ba2969bae102431539 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ToolbarFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ToolbarFragment.kt
@@ -14,8 +14,8 @@ import de.kuschku.libquassel.quassel.BufferInfo
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.util.hasFlag
 import de.kuschku.quasseldroid_ng.R
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.Settings
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings
+import de.kuschku.quasseldroid_ng.settings.Settings
 import de.kuschku.quasseldroid_ng.ui.viewmodel.QuasselViewModel
 import de.kuschku.quasseldroid_ng.util.helper.visibleIf
 import de.kuschku.quasseldroid_ng.util.helper.zip
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferViewConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferViewConfigFragment.kt
index 490fd7b597140b84222e0088b29d3d2b37bc46c0..70b1a339acb1b1148a7039859d52abb0beb787ee 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferViewConfigFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/buffers/BufferViewConfigFragment.kt
@@ -19,8 +19,8 @@ import de.kuschku.libquassel.util.hasFlag
 import de.kuschku.libquassel.util.minus
 import de.kuschku.quasseldroid_ng.R
 import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.Settings
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings
+import de.kuschku.quasseldroid_ng.settings.Settings
 import de.kuschku.quasseldroid_ng.ui.viewmodel.QuasselViewModel
 import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread
 import de.kuschku.quasseldroid_ng.util.helper.map
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/MessageAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/MessageAdapter.kt
index f02013c80c2098bb52dfc63d8c893aa2bd3a0426..57bbb6fd7172ffc0d2d4cd519482ec2b67f9e73e 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/MessageAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/MessageAdapter.kt
@@ -10,7 +10,7 @@ import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.util.hasFlag
 import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
 import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase.DatabaseMessage
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings
 import de.kuschku.quasseldroid_ng.util.helper.getOrPut
 
 class MessageAdapter(
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/MessageListFragment.kt
index 4af1ef6d7fc2e023a1bfdaaa8b1e498d2c43bbd1..b08403f7eac1ea5fdedc64c3e791cb94a296bd97 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/MessageListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/MessageListFragment.kt
@@ -18,9 +18,9 @@ import de.kuschku.libquassel.protocol.MsgId
 import de.kuschku.libquassel.quassel.syncables.BufferSyncer
 import de.kuschku.quasseldroid_ng.R
 import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.BacklogSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.Settings
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings
+import de.kuschku.quasseldroid_ng.settings.BacklogSettings
+import de.kuschku.quasseldroid_ng.settings.Settings
 import de.kuschku.quasseldroid_ng.ui.viewmodel.QuasselViewModel
 import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread
 import de.kuschku.quasseldroid_ng.util.helper.*
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/QuasselMessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/QuasselMessageRenderer.kt
index c86f30d0dc67b38bd7e35d1b9a0a2dd1cee27889..940ac0579de71b22fece24974fffc694aa6c6402 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/QuasselMessageRenderer.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/messages/QuasselMessageRenderer.kt
@@ -15,9 +15,9 @@ import de.kuschku.libquassel.protocol.MsgId
 import de.kuschku.libquassel.util.hasFlag
 import de.kuschku.quasseldroid_ng.R
 import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings.ColorizeNicknamesMode
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings.ShowPrefixMode
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings.ColorizeNicknamesMode
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings.ShowPrefixMode
 import de.kuschku.quasseldroid_ng.util.helper.styledAttributes
 import de.kuschku.quasseldroid_ng.util.helper.visibleIf
 import de.kuschku.quasseldroid_ng.util.irc.format.IrcFormatDeserializer
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/settings/SettingsFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/settings/SettingsFragment.kt
index 6762bd534b0e0276524d4109ba9a35ab041e2f81..bea6fb418264a3611b5ca04c141dca41586a0715 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/settings/SettingsFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/settings/SettingsFragment.kt
@@ -7,8 +7,8 @@ import android.support.v7.preference.Preference
 import android.support.v7.preference.PreferenceFragmentCompat
 import android.support.v7.preference.PreferenceGroup
 import de.kuschku.quasseldroid_ng.R
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.Settings
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings
+import de.kuschku.quasseldroid_ng.settings.Settings
 
 class SettingsFragment : PreferenceFragmentCompat(),
                          SharedPreferences.OnSharedPreferenceChangeListener {
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/CharSequenceHelper.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/CharSequenceHelper.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f7ce68880866306742f45ef1670a03914e3c232f
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/CharSequenceHelper.kt
@@ -0,0 +1,15 @@
+package de.kuschku.quasseldroid_ng.util.helper
+
+fun CharSequence.lastWord(cursor: Int = this.length,
+                          onlyBeforeCursor: Boolean = false): CharSequence {
+  val beginningOfWord = lastIndexOf(' ', cursor)
+  val endOfWord = indexOf(' ', cursor)
+  val start = beginningOfWord + 1
+  val end = if (endOfWord != -1) {
+    endOfWord
+  } else {
+    length
+  }
+
+  return subSequence(start, if (onlyBeforeCursor) cursor else end)
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt
index 7a500a5436f0b0952b3961bdec1e7a6f68027542..b2d19464201f4405e317207914f6362053e0a8e4 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt
@@ -11,9 +11,9 @@ import android.support.v7.app.AppCompatActivity
 import de.kuschku.libquassel.session.Backend
 import de.kuschku.quasseldroid_ng.Keys
 import de.kuschku.quasseldroid_ng.R
-import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.ConnectionSettings
-import de.kuschku.quasseldroid_ng.ui.settings.data.Settings
+import de.kuschku.quasseldroid_ng.settings.AppearanceSettings
+import de.kuschku.quasseldroid_ng.settings.ConnectionSettings
+import de.kuschku.quasseldroid_ng.settings.Settings
 import de.kuschku.quasseldroid_ng.util.helper.sharedPreferences
 import de.kuschku.quasseldroid_ng.util.helper.updateRecentsHeaderIfExisting
 
diff --git a/app/src/main/res/layout/layout_editor.xml b/app/src/main/res/layout/layout_editor.xml
index a8bc035afe7f2d862c2d2a2aa07f9e4678f7d30f..401e590744057e32f36e9d46c75d9d6747e585e2 100644
--- a/app/src/main/res/layout/layout_editor.xml
+++ b/app/src/main/res/layout/layout_editor.xml
@@ -8,13 +8,11 @@
     android:id="@+id/chatline_scroller"
     android:layout_width="0dp"
     android:layout_height="0dp"
-    android:layout_marginBottom="8dp"
-    app:layout_constraintBottom_toTopOf="@+id/formatting_toolbar_container"
+    app:layout_constraintBottom_toTopOf="@+id/autocomplete_list2"
     app:layout_constraintEnd_toStartOf="@+id/send"
     app:layout_constraintHorizontal_bias="1.0"
     app:layout_constraintStart_toStartOf="parent"
-    app:layout_constraintTop_toTopOf="parent"
-    app:layout_constraintVertical_bias="0.0">
+    app:layout_constraintTop_toTopOf="parent">
 
     <android.support.v7.widget.AppCompatEditText
       android:id="@+id/chatline"
@@ -48,6 +46,13 @@
     app:layout_constraintEnd_toEndOf="parent"
     app:srcCompat="@drawable/ic_send" />
 
+  <android.support.v7.widget.RecyclerView
+    android:id="@+id/autocomplete_list2"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:maxHeight="144dp"
+    app:layout_constraintBottom_toTopOf="@+id/formatting_toolbar_container" />
+
   <android.support.design.widget.AppBarLayout
     android:id="@+id/formatting_toolbar_container"
     android:layout_width="match_parent"
diff --git a/app/src/main/res/layout/layout_main.xml b/app/src/main/res/layout/layout_main.xml
index 9ec10cd07dc99d438c1eaa12d7cc9e6f104ddf27..9c856a9a860e81aa520afa97cf3710664bf0449c 100644
--- a/app/src/main/res/layout/layout_main.xml
+++ b/app/src/main/res/layout/layout_main.xml
@@ -19,12 +19,26 @@
     app:umanoScrollableView="@id/chatline_scroller"
     app:umanoShadowHeight="4dp">
 
-    <fragment
-      android:id="@+id/fragment_messages"
-      android:name="de.kuschku.quasseldroid_ng.ui.chat.messages.MessageListFragment"
+    <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
-      tools:layout="@layout/fragment_messages" />
+      android:orientation="vertical">
+
+      <fragment
+        android:id="@+id/fragment_messages"
+        android:name="de.kuschku.quasseldroid_ng.ui.chat.messages.MessageListFragment"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        tools:layout="@layout/fragment_messages" />
+
+      <android.support.v7.widget.RecyclerView
+        android:id="@+id/autocomplete_list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:maxHeight="144dp" />
+
+    </LinearLayout>
 
     <include layout="@layout/layout_slider" />
 
diff --git a/app/src/main/res/values/strings_preferences.xml b/app/src/main/res/values/strings_preferences.xml
index d68f77ebb1541711c16485162dfc18bccd6b48a9..1d111f867451dc552693ecdf162ba47e63d82be9 100644
--- a/app/src/main/res/values/strings_preferences.xml
+++ b/app/src/main/res/values/strings_preferences.xml
@@ -89,6 +89,9 @@
     <item>SEND</item>
   </string-array>
 
+  <string name="preference_autocomplete_key" translatable="false">autocomplete</string>
+  <string name="preference_autocomplete_title">Show AutoComplete UI</string>
+
   <string name="preference_hostmask_key" translatable="false">hostmask</string>
   <string name="preference_hostmask_title">Show Hostmask</string>
   <string name="preference_hostmask_summary">Display the full nick!ident@host in messages</string>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index bffc6e13fdd970ba3a181413b4d78aa83c074e6b..52f4a061c05472d820269c41d283ad4e06955e6d 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -51,6 +51,11 @@
       android:key="@string/preference_show_prefix_key"
       android:title="@string/preference_show_prefix_title" />
 
+    <SwitchPreference
+      android:defaultValue="true"
+      android:key="@string/preference_autocomplete_key"
+      android:title="@string/preference_autocomplete_title" />
+
     <SwitchPreference
       android:defaultValue="false"
       android:key="@string/preference_hostmask_key"