/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id$ */
package org.apache.fop.render.afp;

import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.junit.Assert;
import org.junit.Test;

import org.xml.sax.SAXException;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.apache.xmlgraphics.io.Resource;
import org.apache.xmlgraphics.io.ResourceResolver;

import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPResourceManager;
import org.apache.fop.afp.DataStream;
import org.apache.fop.afp.Factory;
import org.apache.fop.afp.fonts.FopCharacterSet;
import org.apache.fop.afp.modca.PageObject;
import org.apache.fop.apps.EnvironmentalProfileFactory;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopConfParser;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.FopFactoryBuilder;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.fonts.EmbeddingMode;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.render.intermediate.IFException;



public class AFPTrueTypeTestCase {
    private String font;

    @Test
    public void testAFPTrueType() throws IOException, SAXException, TransformerException, URISyntaxException {
        String fo = "<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\n"
                + "  <fo:layout-master-set>\n"
                + "    <fo:simple-page-master master-name=\"simple\">\n"
                + "      <fo:region-body />\n"
                + "    </fo:simple-page-master>\n"
                + "  </fo:layout-master-set>\n"
                + "  <fo:page-sequence master-reference=\"simple\">\n"
                + "    <fo:flow flow-name=\"xsl-region-body\">\n"
                + "      <fo:block font-family=\"Univers\">Univers</fo:block>\n"
                + "      <fo:block font-family=\"Times\">Times</fo:block>\n"
                + "    </fo:flow>\n"
                + "  </fo:page-sequence>\n"
                + "</fo:root>";
        String format = "BEGIN RESOURCE_GROUP RG000001\n"
                + "BEGIN NAME_RESOURCE RES00001 Triplets: OBJECT_FUNCTION_SET_SPECIFICATION"
                + ",OBJECT_CLASSIFICATION,0x01,FULLY_QUALIFIED_NAME,\n"
                + "BEGIN OBJECT_CONTAINER OC000001 Triplets: 0x41,0x00,0x00,\n";
        for (int i = 0; i < 29; i++) {
            format += "DATA OBJECT_CONTAINER\n";
        }
        format += "END OBJECT_CONTAINER OC000001\n"
                + "END NAME_RESOURCE RES00001\n"
                + "END RESOURCE_GROUP RG000001\n"
                + "BEGIN DOCUMENT DOC00001\n"
                + "BEGIN PAGE_GROUP PGP00001\n"
                + "BEGIN PAGE PGN00001\n"
                + "BEGIN ACTIVE_ENVIRONMENT_GROUP AEG00001\n"
                + "MAP DATA_RESOURCE Triplets: 0x01,FULLY_QUALIFIED_NAME,FULLY_QUALIFIED_NAME,OBJECT_CLASSIFICATION,"
                + "DATA_OBJECT_FONT_DESCRIPTOR,\n"
                + "MAP CODED_FONT Triplets: FULLY_QUALIFIED_NAME,FULLY_QUALIFIED_NAME,CHARACTER_ROTATION,"
                + "RESOURCE_LOCAL_IDENTIFIER,\n"
                + "DESCRIPTOR PAGE\n"
                + "MIGRATION PRESENTATION_TEXT\n"
                + "END ACTIVE_ENVIRONMENT_GROUP AEG00001\n"
                + "BEGIN PRESENTATION_TEXT PT000001\n"
                + "DATA PRESENTATION_TEXT\n"
                + "END PRESENTATION_TEXT PT000001\n"
                + "END PAGE PGN00001\n"
                + "END PAGE_GROUP PGP00001\n"
                + "END DOCUMENT DOC00001\n";

        Assert.assertEquals(getAFP(fo), format);
        Assert.assertEquals("test/resources/fonts/ttf/DejaVuLGCSerif.ttf", font);
    }

    @Test
    public void testSVGAFPTrueType() throws IOException, SAXException, TransformerException, URISyntaxException {
        String fo = "<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\" "
                + "xmlns:fox=\"http://xmlgraphics.apache.org/fop/extensions\" "
                + "xmlns:svg=\"http://www.w3.org/2000/svg\">\n"
                + "  <fo:layout-master-set>\n"
                + "    <fo:simple-page-master master-name=\"simple\" page-height=\"27.9cm\" page-width=\"21.6cm\">\n"
                + "      <fo:region-body />\n"
                + "    </fo:simple-page-master>\n"
                + "  </fo:layout-master-set>\n"
                + "  <fo:page-sequence master-reference=\"simple\">\n"
                + "    <fo:flow flow-name=\"xsl-region-body\">   \n"
                + "      <fo:block font-size=\"0\">\n"
                + "        <fo:instream-foreign-object content-height=\"792pt\" content-width=\"612pt\">\n"
                + "          <svg:svg viewBox=\"0 0 816 1056\" height=\"1056\" width=\"816\" id=\"svg2\" "
                + "version=\"1.1\">\n"
                + "            <svg:g transform=\"matrix(1.3333333,0,0,-1.3333333,0,1056)\" id=\"g10\">\n"
                + "              <svg:g id=\"g12\">\n"
                + "                <svg:g id=\"g14\">\n"
                + "                  <svg:g transform=\"translate(36,18)\" id=\"g40\">\n"
                + "                    <svg:text id=\"text44\" style=\"font-variant:normal;font-weight:normal;"
                + "font-size:9px;font-family:Univers;-inkscape-font-specification:ArialMT;writing-mode:lr-tb;"
                + "fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none\" "
                + "transform=\"matrix(1,0,0,-1,44.92,11.4)\">\n"
                + "                      <svg:tspan id=\"tspan42\" y=\"0\" x=\"0.0\">W</svg:tspan>\n"
                + "                    </svg:text>\n"
                + "                  </svg:g>\n"
                + "                  <svg:g id=\"g2672\"/>\n"
                + "                </svg:g>\n"
                + "              </svg:g>\n"
                + "            </svg:g>\n"
                + "          </svg:svg>\n"
                + "        </fo:instream-foreign-object>\n"
                + "      </fo:block>\n"
                + "    </fo:flow>\n"
                + "  </fo:page-sequence>\n"
                + "</fo:root>";
        Assert.assertTrue(getAFP(fo).contains("DATA GRAPHICS"));
    }

    private String getAFP(String fo) throws IOException, TransformerException, SAXException, URISyntaxException {
        String fopxconf = "<fop version=\"1.0\">\n"
                + "  <renderers>\n"
                + "    <renderer mime=\"application/x-afp\">\n"
                + "      <fonts>\n"
                + "        <font name=\"Univers\" embed-url=\"test/resources/fonts/ttf/DejaVuLGCSerif.ttf\">\n"
                + "          <font-triplet name=\"Univers\" style=\"normal\" weight=\"normal\"/>\n"
                + "          <font-triplet name=\"any\" style=\"normal\" weight=\"normal\"/>\n"
                + "        </font>\n"
                + "        <font>\n"
                + "          <afp-font name=\"Times Roman\" type=\"raster\" codepage=\"T1V10500\" encoding=\"Cp500\">\n"
                + "            <afp-raster-font size=\"12\" characterset=\"C0N200B0\" base14-font=\"TimesRoman\"/>\n"
                + "          </afp-font>\n"
                + "          <font-triplet name=\"Times\" style=\"normal\" weight=\"normal\"/>\n"
                + "        </font>"
                + "      </fonts>\n"
                + "    </renderer>\n"
                + "  </renderers>\n"
                + "</fop>";
        FopFactoryBuilder confBuilder = new FopConfParser(
                new ByteArrayInputStream(fopxconf.getBytes()),
                EnvironmentalProfileFactory.createRestrictedIO(new URI("."),
                        new MyResourceResolver())).getFopFactoryBuilder();
        FopFactory fopFactory = confBuilder.build();
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        Fop fop = fopFactory.newFop("application/x-afp", foUserAgent, bos);
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer();
        Source src = new StreamSource(new ByteArrayInputStream(fo.getBytes()));
        Result res = new SAXResult(fop.getDefaultHandler());
        transformer.transform(src, res);
        bos.close();

        StringBuilder sb = new StringBuilder();
        InputStream bis = new ByteArrayInputStream(bos.toByteArray());
        new AFPParser(false).read(bis, sb);
        return sb.toString();
    }

    class MyResourceResolver implements ResourceResolver {
        private ResourceResolver defaultResourceResolver = ResourceResolverFactory.createDefaultResourceResolver();
        public Resource getResource(URI uri) throws IOException {
            if (!"tmp".equals(uri.getScheme())) {
                font = uri.getPath();
                uri = new File(".", uri.getPath()).toURI();
            }
            return defaultResourceResolver.getResource(uri);
        }

        public OutputStream getOutputStream(URI uri) throws IOException {
            return defaultResourceResolver.getOutputStream(uri);
        }
    }

    @Test
    public void testAFPPainter() throws IFException, IOException {
        AFPDocumentHandler afpDocumentHandler = mock(AFPDocumentHandler.class);
        when(afpDocumentHandler.getPaintingState()).thenReturn(new AFPPaintingState());
        when(afpDocumentHandler.getResourceManager()).thenReturn(new AFPResourceManager(null));

        DataStream ds = mock(DataStream.class);
        when(afpDocumentHandler.getDataStream()).thenReturn(ds);
        PageObject po = new PageObject(new Factory(), "PAGE0001", 0, 0, 0, 0, 0);
        when(ds.getCurrentPage()).thenReturn(po);

        AFPPainter afpPainter = new MyAFPPainter(afpDocumentHandler);
        afpPainter.setFont("any", "normal", 400, null, null, Color.BLACK);
        afpPainter.drawText(0, 0, 0, 0, null, "test");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        po.writeToStream(bos);

        InputStream bis = new ByteArrayInputStream(bos.toByteArray());
        StringBuilder sb = new StringBuilder();
        new AFPParser(true).read(bis, sb);
        Assert.assertTrue(sb.toString(),
                sb.toString().contains("DATA PRESENTATION_TEXT AMB AMI SCFL TRN t TRN e TRN s TRN t"));
    }

    @Test
    public void testAFPPainterWidths() throws IFException, IOException {
        AFPDocumentHandler afpDocumentHandler = mock(AFPDocumentHandler.class);
        when(afpDocumentHandler.getPaintingState()).thenReturn(new AFPPaintingState());
        when(afpDocumentHandler.getResourceManager()).thenReturn(new AFPResourceManager(null));

        DataStream ds = mock(DataStream.class);
        when(afpDocumentHandler.getDataStream()).thenReturn(ds);
        PageObject po = new PageObject(new Factory(), "PAGE0001", 0, 0, 0, 0, 0);
        when(ds.getCurrentPage()).thenReturn(po);

        AFPPainter afpPainter = new MyAFPPainter(afpDocumentHandler);
        afpPainter.setFont("any", "normal", 400, null, 12000, Color.BLACK);
        afpPainter.drawText(0, 0, 0, 0, null, "abcdefghijklmno");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        po.writeToStream(bos);
        InputStream bis = new ByteArrayInputStream(bos.toByteArray());
        StringBuilder sb = new StringBuilder();
        AFPParser afpParser = new AFPParser(true);
        afpParser.readWidths = true;
        afpParser.read(bis, sb);
        Assert.assertTrue(sb.toString(), sb.toString().contains("DATA PRESENTATION_TEXT AMB AMI 0 SCFL SVI TRN a AMI"
                + " 9 TRN b AMI 29 TRN c AMI 59 TRN d AMI 99 TRN e AMI 149 TRN f AMI 209 TRN g AMI 24 TRN h AMI 105 TRN"
                + " i AMI 196 TRN j AMI 42 TRN k AMI 153 TRN l AMI 19 TRN m AMI 151 TRN n AMI 38 TRN o AMI 190"));
    }

    class MyAFPPainter extends AFPPainter {
        MyAFPPainter(AFPDocumentHandler documentHandler) {
            super(documentHandler);
        }

        protected FOUserAgent getUserAgent() {
            FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
            return fopFactory.newFOUserAgent();
        }

        protected FontInfo getFontInfo() {
            FontInfo f = new FontInfo();
            f.addFontProperties("any", FontTriplet.DEFAULT_FONT_TRIPLET);
            MultiByteFont font = new MultiByteFont(null, EmbeddingMode.AUTO) {
                public void setWidthArray(int[] wds) {
                    super.setWidthArray(wds);
                    for (int i = 'a'; i <= 'z'; i++) {
                        addPrivateUseMapping(i, i);
                    }
                }
            };
            int[] widths = new int[200];
            for (int i = 0; i < widths.length; i++) {
                widths[i] = 1000 + (i * 256);
            }
            font.setWidthArray(widths);
            f.addMetrics("any", new AFPFontConfig.AFPTrueTypeFont("", true,
                    new FopCharacterSet("", "UTF-16BE", "", font, null, null), null, null, null));
            return f;
        }
    }
}
