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 ComponentNamedElementProcessor extends AbstractDefaultElementModelProcessor {

	private static final int PRECEDENCE = 75;

	protected static final String THYMELEAF_FRAGMENT_PREFIX = "th";
	protected static final String THYMELEAF_FRAGMENT_ATTRIBUTE = "fragment";
	protected static final String REPLACE_CONTENT_TAG = "tc:content";

	private final String fragmentName;

	public ComponentNamedElementProcessor(final String dialectPrefix, final String tagName,
	        final String fragmentName) {
		super(TemplateMode.HTML, "", dialectPrefix + "-" + tagName, true, null,
		    false, PRECEDENCE);
		this.fragmentName = fragmentName;
	}

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

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

		String param = attrMap.get("param");

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

		IModel frag = FragmentHelper.getFragmentModel(context,
		    fragmentName + (param == null ? "" : "(" + param + ")"),
		    structureHandler, THYMELEAF_FRAGMENT_PREFIX,
		    THYMELEAF_FRAGMENT_ATTRIBUTE);

		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(REPLACE_CONTENT_TAG)) {
					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(REPLACE_CONTENT_TAG)) {
					mergedModel.remove(i);
					break;
				}
			}
		}
		return mergedModel;
	}

}

@@ -137,196 +137,64 @@
 el.I
-CloseElementTag;%0Aimport org.thymeleaf.model.IModel;%0Aimport org.thymeleaf.model.IOpenElementTag;%0Aimport org.thymeleaf.model.IProcessableElementTag;%0Aimport org.thymeleaf.model.ITemplateEvent
+Model;%0Aimport org.thymeleaf.model.IProcessableElementTag
 ;%0Aim
@@ -1673,1093 +1673,36 @@
 base
-));%0A%0A%09%7D%0A%0A%09private IModel mergeModel(IModel fragment, IModel body) %7B%0A%09%09IModel mergedModel = insert(fragment, body);%0A%09%09mergedModel = remove(mergedModel);%0A%09%09mergedModel = remove(mergedModel);%0A%09%09return mergedModel;%0A%09%7D%0A%0A%09private IModel insert(IModel fragment, IModel body) %7B%0A%09%09IModel mergedModel = fragment.cloneModel();%0A%09%09int size = mergedModel.size();%0A%09%09ITemplateEvent event = null;%0A%09%09for (int i = 0; i %3C size; i++) %7B%0A%09%09%09event = mergedModel.get(i);%0A%09%09%09if (event instanceof IOpenElementTag) %7B%0A%09%09%09%09if (event.toString().contains(REPLACE_CONTENT_TAG)) %7B%0A%09%09%09%09%09mergedModel.insertModel(i, body);%0A%09%09%09%09%09break;%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return mergedModel;%0A%09%7D%0A%0A%09private IModel remove(IModel fragment) %7B%0A%09%09IModel mergedModel = fragment.cloneModel();%0A%09%09int size = mergedModel.size();%0A%09%09ITemplateEvent event = null;%0A%09%09for (int i = 0; i %3C size; i++) %7B%0A%09%09%09event = mergedModel.get(i);%0A%09%09%09if (event instanceof IOpenElementTag%0A%09%09%09        %7C%7C event instanceof ICloseElementTag) %7B%0A%09%09%09%09if (event.toString().contains(REPLACE_CONTENT_TAG)) %7B%0A%09%09%09%09%09mergedModel.remove(i);%0A%09%09%09%09%09break;%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return mergedModel;%0A%09%7D
+, REPLACE_CONTENT_TAG));%0A%09%7D%0A
 %0A%0A%7D%0A

Remove duplicate code