package org.verapdf.model.impl.pb.pd.font;

import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.font.*;
import org.verapdf.model.baselayer.Object;
import org.verapdf.model.external.FontProgram;
import org.verapdf.model.factory.font.FontFactory;
import org.verapdf.model.impl.pb.external.PBoxFontProgram;
import org.verapdf.model.impl.pb.external.PBoxTrueTypeFontProgram;
import org.verapdf.model.impl.pb.pd.PBoxPDResources;
import org.verapdf.model.pdlayer.PDFont;
import org.verapdf.model.tools.IDGenerator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author Timur Kamalov
 */
public abstract class PBoxPDFont extends PBoxPDResources implements PDFont {

	public static final String FONT_FILE = "fontFile";

	private final String id;

	protected PBoxPDFont(PDFontLike font, final String type) {
		super(font, type);
		this.id = IDGenerator.generateID(font);
	}

	@Override
	public String getID() {
		return this.id;
	}

	@Override
	public String getType() {
		String type = null;
		if (this.pdFontLike instanceof org.apache.pdfbox.pdmodel.font.PDFont) {
			type = ((org.apache.pdfbox.pdmodel.font.PDFont) this.pdFontLike)
					.getType();
		} else if (this.pdFontLike instanceof PDCIDFont) {
			type = ((PDCIDFont) this.pdFontLike).getCOSObject().getNameAsString(
					COSName.TYPE);
		}
		return type;
	}

	@Override
	public String getSubtype() {
		String subtype = null;
		if (this.pdFontLike instanceof org.apache.pdfbox.pdmodel.font.PDFont) {
			subtype = ((org.apache.pdfbox.pdmodel.font.PDFont) this.pdFontLike)
					.getSubType();
		} else if (this.pdFontLike instanceof PDCIDFont) {
			subtype = ((PDCIDFont) this.pdFontLike).getCOSObject().getNameAsString(
					COSName.SUBTYPE);
		}
		return subtype;
	}

	@Override
	public String getBaseFont() {
		return this.pdFontLike.getName();
	}

	@Override
	public Boolean getisSymbolic() {
		PDFontDescriptor fontDescriptor = this.pdFontLike.getFontDescriptor();
		return Boolean.valueOf(fontDescriptor.isSymbolic());
	}

	@Override
	public List<? extends Object> getLinkedObjects(String link) {
		if (FONT_FILE.equals(link)) {
			return this.getFontFile();
		}
		return super.getLinkedObjects(link);
	}

	private List<FontProgram> getFontFile() {
		if (!getSubtype().equals(FontFactory.TYPE_3)
				&& (this.pdFontLike.isEmbedded())) {
			if (getSubtype().equals(FontFactory.TRUE_TYPE)) {
				PBoxTrueTypeFontProgram trueTypeFontProgram = new PBoxTrueTypeFontProgram(
						((PDTrueTypeFont) this.pdFontLike).getTrueTypeFont(), getisSymbolic());
				return this.getFontProgramList(trueTypeFontProgram);
			} else {
				PDFontDescriptor fontDescriptor = pdFontLike.getFontDescriptor();
				PDStream fontFile;
				if (getSubtype().equals(FontFactory.TYPE_1)) {
					if (this.pdFontLike instanceof PDType1CFont) {
						fontFile = fontDescriptor.getFontFile3();
					} else {
						fontFile = fontDescriptor.getFontFile();
					}
				} else if (getSubtype().equals(FontFactory.CID_FONT_TYPE_2)) {
					fontFile = fontDescriptor.getFontFile2();
				} else {
					fontFile = fontDescriptor.getFontFile3();
				}
				if (fontFile != null) {
					return this.getFontProgramList(new PBoxFontProgram(fontFile));
				}
			}
		}
		return Collections.emptyList();
	}

	private List<FontProgram> getFontProgramList(FontProgram fontProgram) {
		List<FontProgram> list = new ArrayList<>(MAX_NUMBER_OF_ELEMENTS);
		list.add(fontProgram);
		return Collections.unmodifiableList(list);
	}

}

@@ -209,16 +209,66 @@
 Object;%0A
+import org.verapdf.model.coslayer.CosUnicodeName;%0A
 import o
@@ -357,16 +357,71 @@
 actory;%0A
+import org.verapdf.model.impl.pb.cos.PBCosUnicodeName;%0A
 import o
@@ -921,16 +921,68 @@
 ntFile%22;
+%0A%09public static final String BASE_FONT = %22BaseFont%22;
 %0A%0A%09priva
@@ -1986,90 +1986,8 @@
 %09%7D%0A%0A
-%09@Override%0A%09public String getBaseFont() %7B%0A%09%09return this.pdFontLike.getName();%0A%09%7D%0A%0A
 %09@Ov
@@ -2239,41 +2239,97 @@
 %7B%0A%09%09
-if (FONT_FILE.equals(link)) %7B
+switch (link) %7B%0A%09%09%09case FONT_FILE:%0A%09%09%09%09return this.getFontFile();%0A%09%09%09case BASE_FONT:
 %0A%09%09%09
+%09
 retu
@@ -2343,24 +2343,34 @@
 .get
-FontFile();%0A%09%09%7D%0A
+BaseFont();%0A%09%09%09default:%0A%09%09
 %09%09re
@@ -2404,16 +2404,20 @@
 (link);%0A
+%09%09%7D%0A
 %09%7D%0A%0A%09pri
@@ -3678,10 +3678,347 @@
 t);%0A%09%7D%0A%0A
+%09private List%3CCosUnicodeName%3E getBaseFont() %7B%0A%09%09String name = this.pdFontLike.getName();%0A%09%09if (name != null) %7B%0A%09%09%09ArrayList%3CCosUnicodeName%3E list = new ArrayList%3C%3E(MAX_NUMBER_OF_ELEMENTS);%0A%09%09%09list.add(new PBCosUnicodeName(COSName.getPDFName(name)));%0A%09%09%09return Collections.unmodifiableList(list);%0A%09%09%7D%0A%09%09return Collections.emptyList();%0A%09%7D%0A%0A
 %7D%0A

Add new link to PDFont