package com.baselet.element.facet.specific;

import java.util.Arrays;
import java.util.List;

import com.baselet.control.SharedUtils;
import com.baselet.control.basics.geom.PointDouble;
import com.baselet.control.basics.geom.Rectangle;
import com.baselet.control.enums.AlignHorizontal;
import com.baselet.control.enums.LineType;
import com.baselet.diagram.draw.DrawHandler;
import com.baselet.diagram.draw.helper.ColorOwn;
import com.baselet.diagram.draw.helper.Style;
import com.baselet.diagram.draw.helper.StyleException;
import com.baselet.element.facet.FirstRunKeyValueFacet;
import com.baselet.element.facet.PropertiesParserState;
import com.baselet.element.sticking.polygon.PointDoubleStickingPolygonGenerator;
import com.baselet.element.sticking.polygon.SimpleStickingPolygonGenerator;

/**
 * must be in first run, because the execution of Class.drawCommonContent() depends on the result of this facet
 */
public class TemplateClassFacet extends FirstRunKeyValueFacet {

	public static final TemplateClassFacet INSTANCE = new TemplateClassFacet();

	private TemplateClassFacet() {}

	public static final int UPPER_SPACE = 3;
	public static final int LOWER_SPACE = 3;
	public static final int LEFT_SPACE = 12;

	@Override
	public KeyValue getKeyValue() {
		return new KeyValue("template", new ValueInfo("text", "print template rectangle on top right corner"));
	}

	@Override
	public void handleValue(String value, PropertiesParserState state) {
		// only act after parsing
	}

	private static int round(double val) {
		return SharedUtils.realignToGrid(false, val, true);
	}

	@Override
	public void parsingFinished(PropertiesParserState state, List<String> handledLines) {
		DrawHandler drawer = state.getDrawer();
		int height = state.getGridElementSize().getHeight();
		int width = state.getGridElementSize().getWidth();
		if (handledLines.isEmpty()) {
			drawer.drawRectangle(0, 0, width, height);
			state.setStickingPolygonGenerator(SimpleStickingPolygonGenerator.INSTANCE);
		}
		else if (handledLines.size() == 1) {
			List<PointDouble> points = TemplateClassFacet.drawTemplateClass(extractValue(handledLines.get(0)), drawer, state, height, width);
			state.setStickingPolygonGenerator(new PointDoubleStickingPolygonGenerator(points));
		}
		else {
			throw new StyleException("Only one class template is allowed");
		}
	}

	private static List<PointDouble> drawTemplateClass(String templateClassText, DrawHandler drawer, PropertiesParserState state, int height, int width) {
		Rectangle tR = calcTemplateRect(templateClassText, drawer, width);
		int classTopEnd = round(tR.getHeight() / 2.0);
		int classWidth = width - round(tR.getWidth() / 2.0);
		PointDouble start = new PointDouble(0, classTopEnd);
		List<PointDouble> p = Arrays.asList(
				start,
				new PointDouble(tR.getX(), classTopEnd),
				new PointDouble(tR.getX(), 0),
				new PointDouble(width, 0),
				new PointDouble(width, tR.getHeight()),
				new PointDouble(classWidth, tR.getHeight()),
				new PointDouble(classWidth, height),
				new PointDouble(0, height),
				start);
		// SET BUFFERS FOR REDUCED CLASS BORDER
		state.getBuffer().setTopMin(tR.getHeight());
		state.getBuffer().addToRight(width - classWidth);
		// DRAW BACKGROUND RECT
		Style style = drawer.getStyleClone();
		drawer.setForegroundColor(ColorOwn.TRANSPARENT);
		drawer.drawLines(p);
		drawer.setStyle(style); // reset style to state before manipulations
		// DRAW RIGHT RECT
		drawer.setLineType(LineType.DASHED);
		drawer.setBackgroundColor(ColorOwn.TRANSPARENT);
		drawer.drawRectangle(tR);
		drawer.setStyle(style); // reset style to state before manipulations
		// DRAW PARTIAL CLASS BORDER
		drawer.drawLines(p.get(1), p.get(0), p.get(7), p.get(6), p.get(5));
		// DRAW TEMPLATE TEXT
		drawer.print(templateClassText, width - drawer.getDistanceBorderToText(), tR.getHeight() - LOWER_SPACE, AlignHorizontal.RIGHT);
		return p;
	}

	private static Rectangle calcTemplateRect(String templateClassText, DrawHandler drawer, int width) {
		double templateHeight = drawer.textHeightMax() + UPPER_SPACE + LOWER_SPACE;
		double templateWidth = drawer.textWidth(templateClassText) + LEFT_SPACE;
		Rectangle tR = new Rectangle(width - templateWidth, 0.0, templateWidth, templateHeight);
		return tR;
	}

}
