/*-
 *  Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
 * 
 *  This file is part of CityDoctor2.
 *
 *  CityDoctor2 is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  CityDoctor2 is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with CityDoctor2.  If not, see <https://www.gnu.org/licenses/>.
 */
package de.hft.stuttgart.citydoctor2.reporting.pdf;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.jdom2.Element;

import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.reporting.ErrorStatisticsCollector;

/**
 * Represents a section in a pdf report
 * 
 * @author Matthias Betz
 *
 */
public class Section {

	private static final String FONT_FAMILY = "font-family";
	private static final String COLOR_TEXT = "color";
	private static final String BASIC_LINK = "basic-link";
	private static final String JUSTIFY = "justify";
	private static final String TEXT_ALIGN_LAST = "text-align-last";
	private static final String MARGIN_LEFT = "margin-left";
	private static final String MARGIN_BOTTOM = "margin-bottom";
	private static final String FONT_WEIGHT = "font-weight";
	private static final String FONT_SIZE = "font-size";
	private static final String BLOCK = "block";
	private static final String TOC_LINE_MARGIN = "5pt";

	private static final AtomicInteger S_COUNTER = new AtomicInteger(0);

	private Element tocBlock;
	private Element contentBlock;

	private Element headlineBlock;

	private String linkId;

	private List<Section> subSections;
	private int depth;

	// attributes for error reporting
	private ErrorStatisticsCollector stats;

	Section(String headline, int depth) {
		this(headline, depth, false);
	}

	Section(String headline, int depth, boolean newPage) {
		this.depth = depth;
		linkId = "s" + S_COUNTER.getAndIncrement();
		tocBlock = new Element(BLOCK, PdfReport.FO_NS);
		PdfReport.applyFont(tocBlock);
		if (depth == 0) {
			tocBlock.setAttribute(FONT_SIZE, "16pt");
		} else if (depth == 1) {
			tocBlock.setAttribute(FONT_SIZE, "14pt");
		} else {
			tocBlock.setAttribute(FONT_SIZE, "12pt");
		}
		tocBlock.setAttribute(FONT_WEIGHT, "bold");
		tocBlock.setAttribute(MARGIN_BOTTOM, TOC_LINE_MARGIN);
		tocBlock.setAttribute(MARGIN_LEFT, (depth + 1) + "0mm");
		tocBlock.setAttribute(TEXT_ALIGN_LAST, JUSTIFY);

		Element tocLine = new Element(BASIC_LINK, PdfReport.FO_NS);
		tocBlock.addContent(tocLine);
		tocLine.setAttribute("internal-destination", linkId);
		tocLine.addContent(headline);

		Element inline = new Element("inline", PdfReport.FO_NS);
		tocLine.addContent(inline);

		Element leader = new Element("leader", PdfReport.FO_NS);
		inline.addContent(leader);
		leader.setAttribute("leader-pattern", "dots");

		Element pageNumberCitation = new Element("page-number-citation", PdfReport.FO_NS);
		tocLine.addContent(pageNumberCitation);
		pageNumberCitation.setAttribute("ref-id", linkId);

		contentBlock = new Element(BLOCK, PdfReport.FO_NS);

		headlineBlock = new Element(BLOCK, PdfReport.FO_NS);
		contentBlock.addContent(headlineBlock);
		if (depth == 0) {
			PdfReport.applyHeadlineAttributes(headlineBlock);
		} else if (depth == 1) {
			PdfReport.applySubHeadlineAttributes(headlineBlock);
		} else {
			PdfReport.applySubSubHeadlineAttributes(headlineBlock);
		}
		headlineBlock.addContent(headline);
		headlineBlock.setAttribute("id", linkId);
		if (newPage) {
			headlineBlock.setAttribute("page-break-before", "always");
		}
	}

	public boolean hasErrors() {
		return stats != null && !stats.getErrorCounts().isEmpty();
	}

	public ErrorStatisticsCollector getStats() {
		if (stats == null) {
			stats = new ErrorStatisticsCollector();
		}
		return stats;
	}

	public void addError(CheckError err) {
		getStats().addError(err.getErrorId().toString());
	}

	public Section createSubSection(String headline) {
		Section sub = new Section(headline, depth + 1);
		if (subSections == null) {
			subSections = new ArrayList<>();
		}
		subSections.add(sub);
		contentBlock.addContent(sub.getContentBlock());
		return sub;
	}

	public void setHeadlineColor(String color) {
		headlineBlock.setAttribute(COLOR_TEXT, color);
		tocBlock.setAttribute(COLOR_TEXT, color);
	}

	public void addTable(Table t) {
		contentBlock.addContent(t.getTableBlock());
	}

	public void addTable(int pos, Table t) {
		contentBlock.addContent(pos, t.getTableBlock());
	}

	public void addTextElement(String text) {
		contentBlock.addContent(PdfReport.createTextElement(text));
	}

	public void addTextElement(String text, String color) {
		Element textBlock = PdfReport.createTextElement(text);
		textBlock.setAttribute(COLOR_TEXT, color);
		contentBlock.addContent(textBlock);
	}

	public void addTextElement(String text, int intend) {
		Element textBlock = PdfReport.createTextElement(text);
		textBlock.setAttribute(MARGIN_LEFT, intend + "mm");
		contentBlock.addContent(textBlock);
	}

	public void add10PtTextElement(String text, int intend) {
		Element textBlock = PdfReport.createTextElement(text);
		textBlock.setAttribute(FONT_SIZE, "10pt");
		textBlock.setAttribute(MARGIN_LEFT, intend + "mm");
		contentBlock.addContent(textBlock);
	}

	public void add12PtTextElement(String text, int intend) {
		Element textBlock = PdfReport.createTextElement(text);
		textBlock.setAttribute(FONT_SIZE, "12pt");
		textBlock.setAttribute(MARGIN_LEFT, intend + "mm");
		contentBlock.addContent(textBlock);
	}

	public void add10PtTextElement(String fontFamily, String text, int intend) {
		Element textBlock = PdfReport.createTextElement(text);
		textBlock.setAttribute(FONT_SIZE, "10pt");
		textBlock.setAttribute(MARGIN_LEFT, intend + "mm");
		textBlock.setAttribute(FONT_FAMILY, fontFamily);
		contentBlock.addContent(textBlock);
	}

	public void addDistributionBar(String title, int redCount, int greenCount) {
		int complete = redCount + greenCount;
		Element distributionBlock = new Element(BLOCK, PdfReport.FO_NS);
		contentBlock.addContent(distributionBlock);
		distributionBlock.addContent(PdfReport.createTextElement(title + " (" + complete + "):"));

		Element distribInstream = new Element("instream-foreign-object", PdfReport.FO_NS);
		distributionBlock.addContent(distribInstream);
		distribInstream.addNamespaceDeclaration(PdfReport.SVG_NS);
		distribInstream.addContent(PdfUtils.createBar(redCount, greenCount));
	}

	Element getContentBlock() {
		return contentBlock;
	}

	Element getTocBlock() {
		return tocBlock;
	}

	List<Section> getSubSections() {
		if (subSections == null) {
			return Collections.emptyList();
		}
		return subSections;
	}

	public void addCodeBlock(CodeBlock codeBlock) {
		contentBlock.addContent(codeBlock.getCodeBlock());
	}

}
