package com.hyperfresh.mchyperchat;

import com.hyperfresh.mchyperchat.field.Field;
import com.hyperfresh.mchyperchat.field.FieldManager;

import java.util.Collection;
import java.util.Map;

public class HyperChat
{
	private HyperChat()
	{

	}

	/**
	 * The current instance of HyperChat
	 */
	private static final HyperChat instance = new HyperChat();

	private HyperChatPlugin plugin = null;

	private final FieldManager fieldManager = new FieldManager();
	private final ThemeManager themeManager = new ThemeManager();
	private final HyperChatEventPoster eventPoster = new HyperChatEventPoster(this);

	/**
	 * Gets the current instance of HyperChat
	 *
	 * @return the current instance of HyperChat.
	 */
	public static HyperChat getInstance()
	{
		return instance;
	}

	/**
	 * This will run when this plugin is enabled.
	 */
	public void setPlugin(HyperChatPlugin plugin)
	{
		this.plugin = plugin;
		//READ "field" FOLDER HERE
	}

	/**
	 * This will run when this plugin is disabled.
	 */
	public void onDisable()
	{
		this.plugin = null;
		this.fieldManager.clear();
	}

	/**
	 * Gets the current console.
	 *
	 * @return the current console
	 */
	public HyperChatPlugin getPlugin()
	{
		return this.plugin;
	}

	public ThemeManager getThemeManager()
	{
		return this.themeManager;
	}

	/**
	 * Get the main list of field.
	 *
	 * @return the main list of field
	 */
	public FieldManager getFieldManager()
	{
		return this.fieldManager;
	}

	public HyperChatEventPoster getEventPoster()
	{
		return this.eventPoster;
	}

	/**
	 * Replaces the existing FieldList with a new one,
	 * effectively deleting all existing field.
	 */
	public void resetFields()
	{
		this.fieldManager.clear();
	}

	private static final String FIELD_REGEX_L = "(?i)\\$\\{", FIELD_REGEX_R = "\\}";

	/**
	 * Replaces all dynamic fields in a string with their values.
	 * Fields are detected by the pattern <code>"${<field name>}"</code>
	 *
	 * @param str
	 * @param user
	 * @return
	 */
	public String processDynamicFields(String str, User user)
	{
		for (Map.Entry<String, Field> e : this.fieldManager.getDynamicFields().entrySet())
		{
			str = str.replaceAll(FIELD_REGEX_L + e.getKey() + FIELD_REGEX_R, e.getValue().getFieldValue(user));
		}

		return str;
	}

	/**
	 * Replaces all static fields in a string with their values.
	 * Fields are detected by the pattern <code>"${<field name>}"</code>
	 *
	 * @param str
	 * @return
	 */
	public String processStaticFields(String str)
	{
		for (Map.Entry<String, Field> e : this.fieldManager.getStaticFields().entrySet())
		{
			str = str.replaceAll(FIELD_REGEX_L + e.getKey() + FIELD_REGEX_R, e.getValue().getFieldValue(null));
		}

		return str;
	}

	/**
	 * Replaces all inlinable fields in a string with their values.
	 * Fields are detected by the pattern <code>"${<field name>}"</code>
	 *
	 * @param str
	 * @return
	 */
	public String processInlineFields(String str, User user)
	{
		for (Map.Entry<String, Field> e : this.fieldManager.getInlinableFields().entrySet())
		{
			str = str.replaceAll(FIELD_REGEX_L + e.getKey() + FIELD_REGEX_R, e.getValue().getFieldValue(user));
		}

		return str;
	}
}
@@ -126,45 +126,115 @@
 ield
-Manager;%0A%0Aimport java.util.Collection
+Flag;%0Aimport com.hyperfresh.mchyperchat.field.FieldManager;%0A%0Aimport java.util.EnumSet;%0Aimport java.util.Map
 ;%0Aim
@@ -248,19 +248,29 @@
 va.util.
-Map
+regex.Matcher
 ;%0A%0Apubli
@@ -1854,16 +1854,331 @@
 %22%5C%5C%7D%22;%0A%0A
+%09private static String processFields(Map%3CString, Field%3E fields, String str, User user)%0A%09%7B%0A%09%09str = Matcher.quoteReplacement(str);%0A%0A%09%09for (Map.Entry%3CString, Field%3E e : fields.entrySet())%0A%09%09%7B%0A%09%09%09str = str.replaceAll(FIELD_REGEX_L + e.getKey() + FIELD_REGEX_R, e.getValue().getFieldValue(user));%0A%09%09%7D%0A%0A%09%09return str;%0A%09%7D%0A%0A
 %09/**%0A%09 *
@@ -2427,215 +2427,106 @@
 %7B%0A%09%09
-for (Map.Entry%3CString, Field%3E e : this.fieldManager.getDynamicFields().entrySet())%0A%09%09%7B%0A%09%09%09str = str.replaceAll(FIELD_REGEX_L + e.getKey() + FIELD_REGEX_R, e.getValue().getFieldValue(user));%0A%09%09%7D%0A%0A%09%09return str
+return processFields(fieldManager.getFieldsByBlacklist(EnumSet.of(FieldFlag.CONSTANT)), str, user)
 ;%0A%09%7D
@@ -2749,221 +2749,124 @@
  str
-)%0A%09%7B%0A%09%09for (Map.Entry%3CString, Field%3E e : this.fieldManager.getStaticFields().entrySet())%0A%09%09%7B%0A%09%09%09str = str.replaceAll(FIELD_REGEX_L + e.getKey() + FIELD_REGEX_R, e.getValue().getFieldValue(null));%0A%09%09%7D%0A%0A%09%09return str
+, User user)%0A%09%7B%0A%09%09return processFields(fieldManager.getFieldsByWhitelist(EnumSet.of(FieldFlag.CONSTANT)), str, user)
 ;%0A%09%7D
@@ -3110,219 +3110,112 @@
 %7B%0A%09%09
-for (Map.Entry%3CString, Field%3E e : this.fieldManager.getInlinableFields().entrySet())%0A%09%09%7B%0A%09%09%09str = str.replaceAll(FIELD_REGEX_L + e.getKey() + FIELD_REGEX_R, e.getValue().getFieldValue(
+return processFields(fieldManager.getFieldsByWhitelist(EnumSet.of(FieldFlag.INLINEABLE)), str, 
 user)
-)
 ;%0A
-%09
 %09%7D%0A%0A
-%09%09return str;%0A%09%7D
 %0A%7D

create private method processFields for less redundancy