/*
 *******************************************************************************
 * Copyright (c) 2020 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************
*/
package org.eclipse.openk.statementpublicaffairs.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.eclipse.openk.statementpublicaffairs.exceptions.BadRequestServiceException;
import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException;
import org.eclipse.openk.statementpublicaffairs.model.AttachmentFile;
import org.eclipse.openk.statementpublicaffairs.model.CompanyContactBlockModel;
import org.eclipse.openk.statementpublicaffairs.model.FontModification;
import org.eclipse.openk.statementpublicaffairs.model.PageContext;
import org.eclipse.openk.statementpublicaffairs.model.TemplateClosingConfig;
import org.eclipse.openk.statementpublicaffairs.model.TemplateClosingConfigSignature;
import org.eclipse.openk.statementpublicaffairs.model.TemplateConfig;
import org.eclipse.openk.statementpublicaffairs.model.TemplateTextBlockConfig;
import org.eclipse.openk.statementpublicaffairs.model.TextState;
import org.eclipse.openk.statementpublicaffairs.model.TextToken;
import org.eclipse.openk.statementpublicaffairs.model.Textblock;
import org.eclipse.openk.statementpublicaffairs.service.compile.TextCompileUtil;
import org.eclipse.openk.statementpublicaffairs.service.compile.Token;
import org.eclipse.openk.statementpublicaffairs.viewmodel.TextConfiguration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

@Service
public class StatementCompileService {

	private static final String TEXT_NL = "\n";
	private static final String TEXT_BULLET = "    • ";
	private static final String TEXT_SPACE = " ";

	private boolean drawRects = false;

	public static final double DPI = 72.0;
	public static final double CM_PER_INCH = 2.54;

	@Value("${statement.compile.dateFormatPattern:\"dd.MM.yyyy\"}")
	private String dateFormatPattern;

	@Value("${statement.compile.statementFileName:\"Statement.pdf\"}")
	private String statementFileName = "Statement.pdf";

	@Value("${statement.compile.templatePdf}")
	private String templatePdfPath;

	@Value("${statement.compile.templateJson}")
	private String templateJsonPath;

	private Map<FontModification, PDFont> fonts;

	@PostConstruct
	public void init() {
		fonts = new HashMap<>();
		fonts.put(FontModification.Normal, PDType1Font.HELVETICA);
		fonts.put(FontModification.Bold, PDType1Font.HELVETICA_BOLD);
		fonts.put(FontModification.Italic, PDType1Font.HELVETICA_OBLIQUE);
	}

	public AttachmentFile generatePDF(TextConfiguration textConfiguration, CompanyContactBlockModel contact,
			List<Textblock> textArrangement) throws InternalErrorServiceException, BadRequestServiceException {
		List<List<TextToken>> textBlockSets = TextCompileUtil.convertToTextTokens(textConfiguration, textArrangement);
		return printPdf(textBlockSets, textConfiguration, contact);
	}

	private PDDocument getTemplatePDF() throws InternalErrorServiceException {
		try {
			File templateFile = ResourceUtils.getFile(templatePdfPath);
			InputStream templateStream = new FileInputStream(templateFile);
			return PDDocument.load(templateStream);
		} catch (IOException e) {
			throw new InternalErrorServiceException("Could not load templatePdf from file " + templatePdfPath, e);
		}
	}

	private TemplateConfig getTemplateConfig() throws InternalErrorServiceException {
		try {
			File file = ResourceUtils.getFile(templateJsonPath);
			ObjectMapper objectMapper = new ObjectMapper();
			return objectMapper.readValue(file, TemplateConfig.class);
		} catch (IOException e) {
			throw new InternalErrorServiceException("Could not load templateConfig from file " + templateJsonPath, e);
		}
	}

	private AttachmentFile printPdf(List<List<TextToken>> textblockSets, TextConfiguration textConfiguration,
			CompanyContactBlockModel contact) throws InternalErrorServiceException, BadRequestServiceException {
		AttachmentFile attachmentFile = new AttachmentFile();
		PDPage firstPageTemplate = null;
		PDPage followupPageTemplate = null;
		TemplateConfig templateConfig = getTemplateConfig();
		PDDocument sourcedoc = getTemplatePDF();
		firstPageTemplate = sourcedoc.getPage(0);
		followupPageTemplate = sourcedoc.getPage(1);

		String welcomeText = String.join(TEXT_NL, templateConfig.getContentP1().getText());
		welcomeText = TextCompileUtil.fillPlaceholder(welcomeText, new HashMap<String, String>(),
				textConfiguration.getReplacements(), textConfiguration.getConfiguration().getSelects());
		List<TextToken> welcomeTokens = TextCompileUtil.parseTextToToken(welcomeText);
		textblockSets.add(0, welcomeTokens);

		PDDocument document = new PDDocument();
		PDDocumentInformation info = document.getDocumentInformation();
		info.setTitle("Statement-" + textConfiguration.getReplacements().get("id"));

		PDPage firstPage = clonePage(firstPageTemplate);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			drawAddressBox(document, firstPage, templateConfig, contact);
			drawInfoBox(document, firstPage, templateConfig, textConfiguration.getReplacements());
			drawContent(document, firstPage, followupPageTemplate, templateConfig, textblockSets);
			document.save(out);
		} catch (IOException e) {
			try {
				document.close();
			} catch (IOException e1) {
				//
			}
			throw new InternalErrorServiceException("Exception when drawing the statement pdf.", e);
		}
		byte[] data = out.toByteArray();
		InputStream is = new ByteArrayInputStream(data);
		attachmentFile.setRessource(is);
		attachmentFile.setName(statementFileName);
		attachmentFile.setType("application/pdf");
		attachmentFile.setLength(out.size());
		return attachmentFile;
	}

	protected float dpiOfCm(double cm) {
		return (float) (cm / CM_PER_INCH * DPI);
	}

	private float calcYPosFromTopCm(double cm, float dpiHeight) {
		return dpiHeight - dpiOfCm(cm);
	}

	private float calcSize(PDFont font, float fontSize, String text) throws IOException {
		return fontSize * font.getStringWidth(text) / 1000;

	}

	private List<String> cutintopieces(PDFont font, float fontSize, String text, double width) throws IOException {
		String[] token = text.split(TEXT_SPACE);
		List<String> lines = new ArrayList<>();
		int tokenIndex = 0;
		List<String> line = new ArrayList<>();
		for (tokenIndex = 0; tokenIndex < token.length; tokenIndex++) {
			line.add(token[tokenIndex]);
			if (calcSize(font, fontSize, String.join(TEXT_SPACE, line)) > width) {
				String tmp = line.remove(line.size() - 1);
				lines.add(String.join(TEXT_SPACE, line));
				line.clear();
				line.add(tmp);
			}

		}
		if (!line.isEmpty()) {
			lines.add(String.join(TEXT_SPACE, line));
		}
		return lines;
	}

	private void drawRect(PageContext context, PDPageContentStream cont) throws IOException {
		if (drawRects) {
			cont.addRect(context.getPosX(), (float) (context.getPosY() + context.getLeading() - context.getHeight()),
					context.getWidth(), context.getHeight());
			cont.setLineWidth(1);
			cont.stroke();
		}
	}

	private void drawContent(PDDocument document, PDPage firstPage, PDPage followupPageTemplate,
			TemplateConfig templateConfig, List<List<TextToken>> textblockSets) throws IOException, BadRequestServiceException {
		List<PDPage> pages = new ArrayList<>();
		boolean first = true;

		List<List<TextToken>> remainingTextSets = new ArrayList<>(textblockSets);
		PDPage currentPage;
		int contextLines;
		PageContext context;
		int pagescount = 0;
		int maxPagesCount = textblockSets.size();
		
		do {
			TemplateTextBlockConfig cfg;
			if (first) {
				currentPage = firstPage;
				cfg = templateConfig.getContentP1();
				first = false;
			} else {
				currentPage = clonePage(followupPageTemplate);
				cfg = templateConfig.getContentP2();
			}
			document.addPage(currentPage);
			pages.add(currentPage);

			PDPageContentStream cont = new PDPageContentStream(document, currentPage, AppendMode.APPEND, false, true);

			context = new PageContext();
			context.setPageHeight(currentPage.getMediaBox().getHeight());
			context.setPosX(dpiOfCm(cfg.getX()));
			context.setPosY(calcYPosFromTopCm(cfg.getY(), context.getPageHeight()));
			context.setWidth(dpiOfCm(cfg.getWidth()));
			context.setHeight(dpiOfCm(cfg.getHeight()));
			context.setLeading(cfg.getFontSize() * 1.12);
			context.setFontSize(templateConfig.getContentP1().getFontSize());

			drawRect(context, cont);

			contextLines = drawContentPage(remainingTextSets, cont, context);
			pagescount++;
			if (pagescount > maxPagesCount) {
				throw new BadRequestServiceException("Error, page could not be printed. Maybe a textblock is too large to fit on one page");
			}

		} while (!remainingTextSets.isEmpty());

		TemplateClosingConfig closingConf = templateConfig.getClosing();
		double height = closingConf.getSalutation().size() * context.getLeading();
		height += dpiOfCm(closingConf.getSignatures().get(0).getYOffset());
		height += (closingConf.getSignatures().get(0).getLines().size() + 2) * context.getLeading();

		float relYCursor = (float) (contextLines * context.getLeading());
		float posYCursor = context.getPosY() - relYCursor;
		PageContext closingContext = new PageContext();
		if ((context.getHeight() - relYCursor) < height) {
			currentPage = clonePage(followupPageTemplate);
			TemplateTextBlockConfig cfg = templateConfig.getContentP2();
			document.addPage(currentPage);
			pages.add(currentPage);
		
			closingContext.setPageHeight(currentPage.getMediaBox().getHeight());
			closingContext.setPosX(dpiOfCm(cfg.getX()));
			closingContext.setPosY(calcYPosFromTopCm(cfg.getY(), closingContext.getPageHeight()));
			closingContext.setWidth(dpiOfCm(cfg.getWidth()));
			closingContext.setHeight((float) height);
			closingContext.setLeading(cfg.getFontSize() * 1.12);
			closingContext.setFontSize(templateConfig.getContentP1().getFontSize());
		} else {
			closingContext.setPageHeight(context.getPageHeight());
			closingContext.setPosX(context.getPosX());
			closingContext.setPosY(posYCursor);
			closingContext.setWidth(context.getWidth());
			closingContext.setHeight((float) height);
			closingContext.setLeading(context.getLeading());
			closingContext.setFontSize(context.getFontSize());
		}

		PDPageContentStream cont = new PDPageContentStream(document, currentPage, AppendMode.APPEND, false, true);

		drawClosing(closingContext, cont, templateConfig.getClosing());

	}

	private void drawClosing(PageContext context, PDPageContentStream cont, TemplateClosingConfig closingConfig)
			throws IOException {

		drawRect(context, cont);

		cont.beginText();
		cont.setFont(fonts.get(FontModification.Normal), context.getFontSize());
		cont.setLeading(context.getLeading());
		cont.newLineAtOffset(context.getPosX(), context.getPosY());
		for (String line : closingConfig.getSalutation()) {
			cont.showText(line);
			cont.newLine();
		}
		float posYCursor = (float) (context.getPosY() - closingConfig.getSalutation().size() * context.getLeading());
		cont.endText();

		for (TemplateClosingConfigSignature signature : closingConfig.getSignatures()) {

			float posY = posYCursor - dpiOfCm(signature.getYOffset());
			float posX = context.getPosX() + dpiOfCm(signature.getXOffset());

			cont.moveTo(posX, posY);
			cont.lineTo(posX + dpiOfCm(signature.getWidth()), posY);
			cont.setLineWidth(0.3f);
			cont.stroke();

			cont.beginText();
			cont.setFont(fonts.get(FontModification.Normal), context.getFontSize());
			cont.setLeading(context.getLeading());
			cont.newLineAtOffset(posX, posY);
			cont.newLine();
			for (String signatureLine : signature.getLines()) {
				cont.showText(signatureLine);
				cont.newLine();
			}
			cont.endText();
		}
		cont.close();
	}

	private int drawContentPage(List<List<TextToken>> remainingTextSets, PDPageContentStream cont, PageContext context)
			throws IOException {
		cont.beginText();
		cont.setLeading(context.getLeading());
		cont.newLineAtOffset(context.getPosX(), context.getPosY());

		DrawContentContext drawContext = new DrawContentContext();
		int resultLines = 0;
		do {

			List<TextToken> set = new ArrayList<>(remainingTextSets.get(0));
			DrawContentContext resultContext = drawTokenList(drawContext, set, context.getWidth(),
					context.getMaxLines(), context.getFontSize(), cont);
			resultLines = resultContext.lines;
			if (resultContext.fitOnPage && !resultContext.pagebreak) {
				remainingTextSets.remove(0);
				drawContext = resultContext;
			} else {
				if (resultContext.fitOnPage && resultContext.pagebreak) {
					remainingTextSets.remove(0);
				}
				break;
			}
		} while (!remainingTextSets.isEmpty());
		cont.endText();
		cont.close();
		return resultLines;
	}

	private DrawContentContext drawTokenList(DrawContentContext context, List<TextToken> set, double maxWidth,
			int maxLines, float fontSize, PDPageContentStream cont) throws IOException {
		DrawContentContext resContext = new DrawContentContext();

		FontModification lastLineFontMode = FontModification.Normal;

		double currentTextWidth = context.currentTextWidth;
		
		// if specialtype
		if (set.size() == 1 && set.get(0).getType() == Token.TK_PB) {
			resContext.pagebreak = true;
			resContext.fitOnPage = true;
			return resContext;
		}
		List<List<TextToken>> lines = new ArrayList<>();
		List<TextToken> line = new ArrayList<>();
		if (currentTextWidth > 0) {
			line.add(TextToken.newSpaceTextToken());
			line.add(TextToken.newSpaceTextToken());
		}
		
		int linecount = 0;
		while (!set.isEmpty()) {
			TextToken token = set.remove(0);
			TextState newState = calculateLineWidth(lastLineFontMode, currentTextWidth, line, token, fontSize);
			resContext.currentTextWidth = newState.getWidth();
			if (newState.isLineBreak()) {
				linecount++;
				line.add(token);
				lines.add(line);
				line = new ArrayList<>();
				resContext.currentTextWidth = 0;
				currentTextWidth = 0;
				lastLineFontMode = newState.getFontMode();

			} else if (newState.getWidth() <= maxWidth) {
				line.add(token);
			} else {
				linecount++;
				line.add(TextToken.newLineTextToken());
				if (newState.isInBulletPoint()) {
					line.add(TextToken.newBulletShiftTextToken());
				}
				lines.add(line);
				line = new ArrayList<>();
				line.add(token);
				currentTextWidth = 0;
				resContext.currentTextWidth = 0;
				lastLineFontMode = newState.getFontMode();
			}
		}
		lines.add(line);
		if (maxLines >= (context.lines + linecount)) {
			drawTextSet(lines, cont, fontSize);
			resContext.lines = context.lines + linecount;
			resContext.fitOnPage = true;
		} else {
			resContext.pagebreak = true;
		}
		return resContext;

	}

	private class DrawContentContext {
		private int lines;
		private double currentTextWidth;
		private boolean fitOnPage;
		private boolean pagebreak;
	}

	private FontModification updateFontMod(FontModification currentFontMod, Token token) {
		FontModification newFontMod;
		switch (token) {
		case TK_BOLD:
			if (currentFontMod == FontModification.Bold) {
				newFontMod = FontModification.Normal;
			} else {
				newFontMod = FontModification.Bold;
			}
			break;
		case TK_ITALIC:
			if (currentFontMod == FontModification.Italic) {
				newFontMod = FontModification.Normal;
			} else {
				newFontMod = FontModification.Italic;
			}
			break;
		default:
			newFontMod = FontModification.Normal;
		}
		return newFontMod;
	}

	private void drawTextSet(List<List<TextToken>> lines, PDPageContentStream cont, float fontSize) throws IOException {
		FontModification currentFontMod = FontModification.Normal;
		boolean inBulletPoint = false;
		for (List<TextToken> line : lines) {
			boolean firstInLine = true;
			for (TextToken lt : line) {
				switch (lt.getType()) {
				case TK_NL:
					cont.newLine();
					inBulletPoint = false;
					break;
				case TK_BOLD:
				case TK_ITALIC:
					currentFontMod = updateFontMod(currentFontMod, lt.getType());
					break;
				case TK_BULLET:
					cont.setFont(fonts.get(currentFontMod), fontSize);
					cont.showText(TEXT_BULLET);
					inBulletPoint = true;
					break;
				case TK_SPACE:
					if (!firstInLine) {
						cont.setFont(fonts.get(currentFontMod), fontSize);
						cont.showText(TEXT_SPACE);
					}
					break;
				case TK_UNDERSCORE:
				case STRING:
					cont.setFont(fonts.get(currentFontMod), fontSize);
					if (firstInLine && inBulletPoint) {
						cont.showText("      ");
					}
					cont.showText(lt.getValue());
					break;
				default:
					break;
				}
				firstInLine = false;
			}
		}
	}

	private TextState calculateLineWidth(FontModification initialFontMod, double currentTextWidth, List<TextToken> line,
			TextToken token, float fontSize) throws IOException {
		List<TextToken> tokens = new ArrayList<>(line);
		tokens.add(token);
		double width = currentTextWidth;
		FontModification currentFontMod = initialFontMod;
		TextState result = new TextState();
		for (TextToken lt : tokens) {
			switch (lt.getType()) {
			case TK_BOLD:
			case TK_ITALIC:
				currentFontMod = updateFontMod(currentFontMod, lt.getType());
				break;
			case TK_SPACE:
				width += calcSize(fonts.get(currentFontMod), fontSize, TEXT_SPACE);
				break;
			case TK_BULLET:
				width += calcSize(fonts.get(currentFontMod), fontSize, TEXT_BULLET);
				result.setInBulletPoint(true);
				break;
			case STRING:
				width += calcSize(fonts.get(currentFontMod), fontSize, lt.getValue());
				break;
			case TK_NL:
				result.setLineBreak(true);
				result.setInBulletPoint(false);
				break;
			default:
				break;
			}
		}
		result.setWidth(width);
		result.setFontMode(currentFontMod);
		return result;
	}

	private void drawInfoBox(PDDocument document, PDPage firstPage, TemplateConfig templateConfig, Map<String, String> replacements) throws IOException {
		PDPageContentStream cont = new PDPageContentStream(document, firstPage, AppendMode.APPEND, false, true);
		float pageHeight = firstPage.getMediaBox().getHeight();

		TemplateTextBlockConfig cfg = templateConfig.getInfo();
		float posX = dpiOfCm(cfg.getX());
		float posY = calcYPosFromTopCm(cfg.getY(), pageHeight);
		float width = dpiOfCm(cfg.getWidth());
		float height = dpiOfCm(cfg.getHeight());

		List<String> text = cfg.getText();

		List<String> lines = new ArrayList<>();
		for (String textEntry : text) {
			textEntry = TextCompileUtil.fillPlaceholder(textEntry, null, replacements, new HashMap<>());
			lines.addAll(cutintopieces(fonts.get(FontModification.Normal), cfg.getFontSize(), textEntry, width));
		}

		double leading = cfg.getFontSize() * 1.12;

		PageContext context = new PageContext();
		context.setPosX(posX);
		context.setPosY(posY);
		context.setLeading(leading);
		context.setWidth(width);
		context.setHeight(height);

		drawRect(context, cont);

		cont.beginText();
		cont.setFont(fonts.get(FontModification.Normal), cfg.getFontSize());
		cont.setLeading(leading);
		cont.newLineAtOffset(posX, posY);

		for (String line : lines) {
			cont.showText(line);
			cont.newLine();
		}
		cont.close();
	}

	private void drawAddressBox(PDDocument document, PDPage firstPage, TemplateConfig templateConfig,
			CompanyContactBlockModel contact) throws IOException {
		List<String> address = new ArrayList<>();
		address.add(contact.getCompany());
		List<String> nameEntries = new ArrayList<>();
		if (contact.getSalutation() != null) {
			nameEntries.add(contact.getSalutation());
		}
		if (contact.getTitle() != null) {
			nameEntries.add(contact.getTitle());
		}
		nameEntries.add(contact.getFirstName());
		nameEntries.add(contact.getLastName());
		address.add(String.join(TEXT_SPACE, nameEntries));
		address.add(contact.getStreet() + contact.getHouseNumber());
		address.add(contact.getPostCode() + TEXT_SPACE + contact.getCommunity());
		if (contact.getCommunitySuffix() != null) {
			address.add(contact.getCommunitySuffix());
		}

		PDPageContentStream cont = new PDPageContentStream(document, firstPage, AppendMode.APPEND, false, true);
		float pageHeight = firstPage.getMediaBox().getHeight();

		TemplateTextBlockConfig addressCfg = templateConfig.getAddress();
		float posX = dpiOfCm(addressCfg.getX());
		float posY = calcYPosFromTopCm(addressCfg.getY(), pageHeight);
		float width = dpiOfCm(addressCfg.getWidth());
		float height = dpiOfCm(addressCfg.getHeight());

		List<String> lines = new ArrayList<>();
		for (String textEntry : address) {
			lines.addAll(cutintopieces(fonts.get(FontModification.Normal), addressCfg.getFontSize(), textEntry, width));
		}

		double leading = addressCfg.getFontSize() * 1.12;
		PageContext context = new PageContext();
		context.setPosX(posX);
		context.setPosY(posY);
		context.setLeading(leading);
		context.setWidth(width);
		context.setHeight(height);
		drawRect(context, cont);

		cont.beginText();
		cont.setFont(fonts.get(FontModification.Normal), addressCfg.getFontSize());
		cont.setLeading(leading);
		cont.newLineAtOffset(posX, posY);

		for (String line : lines) {
			cont.showText(line);
			cont.newLine();
		}
		cont.endText();
		cont.close();
	}

	private PDPage clonePage(PDPage original) {
		COSDictionary pageDict = original.getCOSObject();
		COSDictionary newPageDict = new COSDictionary(pageDict);
		newPageDict.removeItem(COSName.ANNOTS);
		return new PDPage(newPageDict);
	}

}
