package de.morphbit.thymeleaf.processor;

import java.util.Map;

import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.model.ICloseElementTag;
import org.thymeleaf.model.IModel;
import org.thymeleaf.model.IOpenElementTag;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.model.ITemplateEvent;
import org.thymeleaf.processor.element.IElementModelStructureHandler;
import org.thymeleaf.templatemode.TemplateMode;

import de.morphbit.thymeleaf.helper.FragmentHelper;

public class ComponentElementProcessor
        extends AbstractDefaultElementModelProcessor {

	private static final String TAG_NAME = "component";
	private static final int PRECEDENCE = 20;

	public ComponentElementProcessor(final String dialectPrefix) {
		super(TemplateMode.HTML, dialectPrefix, TAG_NAME, true, null, false,
		    PRECEDENCE);
	}

	@Override
	protected void doProcess(ITemplateContext context, IModel model,
	        IElementModelStructureHandler structureHandler) {

		IProcessableElementTag tag = processElementTag(context, model);
		Map<String, String> attrMap = processAttribute(context, tag);

		IModel base = model.cloneModel();
		base.remove(0);
		base.remove(base.size() - 1);

		IModel frag = FragmentHelper.getFragmentModel(context,
		    attrMap.get("name"), structureHandler, "th", "fragment");

		model.reset();
		model.addModel(mergeModel(frag, base));

	}

	private IModel mergeModel(IModel fragment, IModel body) {
		IModel mergedModel = insert(fragment, body);
		mergedModel = remove(mergedModel);
		mergedModel = remove(mergedModel);
		return mergedModel;
	}

	private IModel insert(IModel fragment, IModel body) {
		IModel mergedModel = fragment.cloneModel();
		int size = mergedModel.size();
		ITemplateEvent event = null;
		for (int i = 0; i < size; i++) {
			event = mergedModel.get(i);
			if (event instanceof IOpenElementTag) {
				if (event.toString().contains("tc:content")) {
					mergedModel.insertModel(i, body);
					break;
				}
			}
		}
		return mergedModel;
	}

	private IModel remove(IModel fragment) {
		IModel mergedModel = fragment.cloneModel();
		int size = mergedModel.size();
		ITemplateEvent event = null;
		for (int i = 0; i < size; i++) {
			event = mergedModel.get(i);
			if (event instanceof IOpenElementTag
			        || event instanceof ICloseElementTag) {
				if (event.toString().contains("tc:content")) {
					mergedModel.remove(i);
					break;
				}
			}
		}
		return mergedModel;
	}

}

@@ -687,16 +687,218 @@
  = 20;%0A%0A
+%09private static final String THYMELEAF_FRAGMENT_PREFIX = %22th%22;%0A%09private static final String THYMELEAF_FRAGMENT_ATTRIBUTE = %22fragment%22;%0A%0A%09private static final String REPLACE_CONTENT_TAG = %22tc:content%22;%0A%0A
 %09public 
@@ -953,16 +953,16 @@
 efix) %7B%0A
-
 %09%09super(
@@ -1508,24 +1508,69 @@
 er, 
-%22th%22, %22fragment%22
+THYMELEAF_FRAGMENT_PREFIX,%0A%09%09    THYMELEAF_FRAGMENT_ATTRIBUTE
 );%0A%0A
@@ -2143,36 +2143,43 @@
 ().contains(
-%22tc:content%22
+REPLACE_CONTENT_TAG
 )) %7B%0A%09%09%09%09%09me
@@ -2606,28 +2606,35 @@
 ontains(
-%22tc:content%22
+REPLACE_CONTENT_TAG
 )) %7B%0A%09%09%09

Make variables final static