/*
 *
 *  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.
 *
 */

package flash.fonts;

import flash.swf.builder.types.ShapeBuilder;
import flash.swf.builder.types.ShapeIterator;
import flash.swf.types.GlyphEntry;
import flash.swf.types.Shape;
import flash.swf.SwfConstants;
import flash.util.Trace;

import org.apache.flex.forks.batik.svggen.font.Font;
import org.apache.flex.forks.batik.svggen.font.Glyph;
import org.apache.flex.forks.batik.svggen.font.Point;
import org.apache.flex.forks.batik.svggen.font.table.CmapFormat;
import org.apache.flex.forks.batik.svggen.font.table.CmapTable;
import org.apache.flex.forks.batik.svggen.font.table.GlyfTable;
import org.apache.flex.forks.batik.svggen.font.table.GlyphDescription;
import org.apache.flex.forks.batik.svggen.font.table.HeadTable;
import org.apache.flex.forks.batik.svggen.font.table.HheaTable;
import org.apache.flex.forks.batik.svggen.font.table.HmtxTable;
import org.apache.flex.forks.batik.svggen.font.table.NameTable;
import org.apache.flex.forks.batik.svggen.font.table.Os2Table;
import org.apache.flex.forks.batik.svggen.font.table.Table;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;

/**
 * This implementation of FontManager uses Apache Batik to process
 * TrueTypeFont Files.
 */
@SuppressWarnings("unchecked")
public class BatikFontManager extends CachedFontManager
{
	private JREFontManager jreManager;
    // Used to initialize the JREFontManager.
	private Map initializeMap;

    public static String processLocation(Object location)
    {
        String path = null;

        if (location != null)
        {
            if (location instanceof URL)
            {
                URL url = (URL)location;
                if (url.getProtocol().toLowerCase().indexOf("file") > -1)
                {
                    path = url.getFile();
                }
            }
            else
            {
                File f = new File(location.toString());
                if (f.exists())
                {
                    path = f.getAbsolutePath();
                }
            }
        }

        return path;
    }

    public void initialize(Map map)
    {
        super.initialize(map);
        initializeMap = map;
    }

	public FontFace getEntryFromSystem(String familyName, int style, boolean useTwips)
	{
		FontManager manager = parent;
		if (manager == null)
		{
			if (jreManager == null)
			{
				jreManager = new JREFontManager();
                jreManager.initialize(initializeMap);
			}
			manager = jreManager;
		}
        return manager.getEntryFromSystem(familyName, style, useTwips);
	}

	protected FontSet createSetForSystemFont(String family, int style, boolean useTwips)
	{
		FontManager manager = parent;
		if (manager == null || ! (manager instanceof CachedFontManager))
		{
			if (jreManager == null)
			{
				jreManager = new JREFontManager();
			}
			manager = jreManager;
		}

        return ((CachedFontManager)manager).createSetForSystemFont(family, style, useTwips);
	}

    public FontFace getEntryFromLocation(URL location, int requestedStyle, boolean useTwips)
    {
    	// C: Batik should only do TT.
    	if (!location.toString().toLowerCase().endsWith(".ttf"))
    	{
        	return (parent != null) ? parent.getEntryFromLocation(location, requestedStyle, useTwips) : null;
    	}
    	
        FontFace entry = null;

        String locationKey = location != null ? location.toExternalForm() : null;
        Object fam = getFontFileCache().get(locationKey);
        if (fam == null)
        {
            fam = createFontFromLocation(location, requestedStyle, useTwips);
        }

        if (fam != null)
        {
            String family = fam.toString();

            FontSet fontSet = (FontSet)getFontCache().get(family);

            // The font file cache should still have this family
            // from the location fetch above...
            if (fontSet != null)
            {
                entry = fontSet.get(requestedStyle);
            }

            // Finally, remember the family for this location
            getFontFileCache().put(locationKey, family);
        }
        else if (parent != null)
        {
        	// C: give the parent font manager a chance...
        	return parent.getEntryFromLocation(location, requestedStyle, useTwips);
        }

        return entry;
    }

    protected String createFontFromLocation(Object location, int requestedStyle, boolean useTwips)
    {
        String family = null;
        String path = processLocation(location);

        if (path != null)
        {
            try
            {
	            // Use Batik to load the Font
	            Font font = Font.create(path);

                if (font != null)
                {
	                FSType type = FSType.getFSType(font);
	                if (! type.usableByFlex)
	                {
		                throw new UnusableFontLicense(location + "", type.description);
	                }
	                String copyright = font.getNameTable().getRecord(Table.nameCopyrightNotice);
	                String trademark = font.getNameTable().getRecord(Table.nameTrademark);

                    // BatikFontManager will try to work out the real
                    // style from the sub family name and update the
                    // style property...
                    BatikFontFace fontFace = new BatikFontFace(font, 0,
                            maxGlyphsPerFace, type, copyright, trademark,
                            useTwips, majorCompatibilityVersion < 3);

                    // From Flex 4 we just use the requested style rather than
                    // validating it matches the style described by the font
                    if (majorCompatibilityVersion > 3)
                        fontFace.style = requestedStyle;

                    family = fontFace.getFamily();

                    FontSet fontSet = (FontSet)getFontCache().get(family);

                    if (fontSet == null)
                    {
                        fontSet = new FontSet(maxFacesPerFont);
                        getFontCache().put(family, fontSet);
                    }

                    fontSet.put(fontFace.style, fontFace);
                }
            }
            catch (UnusableFontLicense l)
            {
	            throw l;
            }
            catch (Throwable t)
            {
                throw new RuntimeException("Unexpected exception encountered while reading font file '" + path + "'");
            }
        }

        return family;
    }

    /*
    public static class BatikRuntimeException extends RuntimeException {
    	public final static long serialVersionUID = -1;
    	public BatikRuntimeException(String s) {super(s);}
    	public BatikRuntimeException(Throwable e) {super(e);}
    }
    */

    public static class BatikFontFace extends CachedFontFace
    {
        static final short PLATFORM_APPLE_UNICODE = 0;
        static final short PLATFORM_MACINTOSH = 1;
        static final short PLATFORM_ISO = 2;
        static final short PLATFORM_MICROSOFT = 3;
        static final short ENCODING_UNDEFINED = 0;
        static final short ENCODING_UGL = 1;
        static final short ENCODING_ROMAN = 0;

        public BatikFontFace(Font font, int style, int maxGlyphs, FSType fsType, String copyright, String trademark,
                             boolean useTwips, boolean keep201Behavior)
        {
            super(maxGlyphs, style, fsType, copyright, trademark, useTwips);
            init(font, keep201Behavior);
        }

        private void init(Font font, boolean keep201Behavior)
        {
            numGlyphs = font.getNumGlyphs();

            processCmapTable(font);
            processNameTable(font);
            processHeadTable(font); //Must process this before HHEA table
            processHheaTable(font);
            processOS2Table(font);

            hmtx = (HmtxTable)font.getTable(Table.hmtx);
            glyf = (GlyfTable)font.getTable(Table.glyf);
            this.keep201Behavior = keep201Behavior; 
        }

        /**
         * Contains multiple mapping tables from Unicode and various 8-bit encodings to glyph ids.
         * Multi-platform.
         */
        private void processCmapTable(Font font)
        {
            CmapTable cmap = font.getCmapTable();

            if (cmap != null)
            {
                // Decide upon a cmap table to use for our character to glyph look-up
                if (forceAscii)
                {
                    // We've been asked to use the ASCII/Macintosh cmap format
                    cmapFmt = cmap.getCmapFormat(Table.platformMacintosh, Table.encodingRoman);
                    platformID = PLATFORM_MACINTOSH;
                    encodingID = ENCODING_ROMAN;
                }
                else
                {
                    // The default behaviour is to use the Unicode cmap encoding
                    cmapFmt = cmap.getCmapFormat(Table.platformMicrosoft, Table.encodingUGL);
                    if (cmapFmt == null)
                    {
                        // This might be a symbol font, so we'll look for an "undefined" encoding
                        cmapFmt = cmap.getCmapFormat(Table.platformMicrosoft, Table.encodingUndefined);
                        platformID = PLATFORM_MICROSOFT;
                        encodingID = ENCODING_UNDEFINED;
                    }
                    else
                    {
                        platformID = PLATFORM_MICROSOFT;
                        encodingID = ENCODING_UGL;
                    }
                }
            }

            if (cmapFmt == null)
            {
                throw new RuntimeException("Cannot find a suitable cmap table");
            }
        }

        /**
         * Contains strings that provide general information about the font.
         * Strings are multilingual and multi-platform and are identified by number.
         * Some numbers have a standard meaning such as font name and copyright.
         * Arbitrary numbered strings can also be present.
         */
        private void processNameTable(Font font)
        {
            NameTable name = font.getNameTable();

            if (name != null)
            {
                fontFamily = name.getRecord(Table.nameFontFamilyName);
                subFamilyName = name.getRecord(Table.nameFontSubfamilyName);
	            postscriptName = name.getRecord(Table.namePostscriptName);

                if (subFamilyName != null)
                {
                    style = guessStyleFromSubFamilyName(subFamilyName);
                }
            }
            else
            {
            	if (Trace.font)
                    Trace.trace("Font " + fontFamily + " did not have an HEAD Table.");
            }
        }

        /**
         * Contains overall font metrics and checksum for font.
         * Also contains font appearance (Mac). Must be called before
         * reading HHEA table.
         */
        private void processHeadTable(Font font)
        {
            HeadTable head = font.getHeadTable();

            if (head != null)
            {
                unitsPerEm = head.getUnitsPerEm();
            }
            else
            {
            	if (Trace.font)
                    Trace.trace("Font " + fontFamily + " did not have an HEAD Table.");
            }

            //Scale points to SWF fixed EM square of 1024 FUnits
            emScale = SWF_EM_SQUARE / (double)unitsPerEm;
        }

        /**
         * Contains overall horizontal metrics and caret slope.
         * Also contains line spacing (Mac).
         */
        private void processHheaTable(Font font)
        {
            HheaTable hhea = font.getHheaTable();

            if (hhea != null)
            {
                //TODO: I'm skeptical about these values, shouldn't the x-height and baseline be taken into consideration here?!
                ascent = (short)Math.rint(hhea.getAscender() * emScale * (useTwips ? SwfConstants.TWIPS_PER_PIXEL : 1));
                descent = (short)Math.rint(hhea.getDescender() * emScale * (useTwips ? SwfConstants.TWIPS_PER_PIXEL : 1));
                lineGap = (short)Math.rint(hhea.getLineGap() * emScale * (useTwips ? SwfConstants.TWIPS_PER_PIXEL : 1));
            }
            else
            {
            	if (Trace.font)
                    Trace.trace("Font " + fontFamily + " did not have an HHEA Table.");
            }
        }

        /**
         * Contains line spacing, font weight, font style, codepoint ranges (codepage and Unicode)
         * covered by glyphs, overall appearance, sub- and super-script support, strike out information.
         */
        private void processOS2Table(Font font)
        {
            Os2Table os2 = font.getOS2Table();

            if (os2 != null)
            {
                if (!forceAscii)
                {
                    int winAscent = os2.getWinAscent();
                    ascent = (short)Math.rint(winAscent * emScale * (useTwips ? SwfConstants.TWIPS_PER_PIXEL : 1));

                    int winDescent = os2.getWinDescent();
                    descent = (short)Math.rint(winDescent * emScale * (useTwips ? SwfConstants.TWIPS_PER_PIXEL : 1));

                    int winLeading = os2.getTypoLineGap();
                    lineGap = (short)Math.rint(winLeading * emScale * (useTwips ? SwfConstants.TWIPS_PER_PIXEL : 1));
                }

                horizAdvanceX = os2.getAvgCharWidth();
                panose = os2.getPanose().toString();
                usFirstCharIndex = os2.getFirstCharIndex();
            }
            else
            {
            	if (Trace.font)
                    Trace.trace("Font " + fontFamily + " did not have an OS/2 Table.");
            }
        }

        //SWF through version 7 does not use kerning information.
        /*
        private void processKernTable(Font font)
        {
            KernTable kern = (KernTable)font.getTable(Table.kern);
            if (kern != null)
            kst = kern.getSubtable(0);
        }
        */

        public boolean canDisplay(char c)
        {
            return cmapFmt.mapCharCode(getCharIndex(c)) > 0;
        }

        public GlyphEntry getGlyphEntry(char c)
        {
            return (GlyphEntry)glyphCache.get(c);
        }

        public GlyphEntry createGlyphEntry(char c)
        {
            return createGlyphEntry(c, c);
        }

        public GlyphEntry createGlyphEntry(char c, char referenceChar)
        {
            int index = getCharIndex(referenceChar);
            index = cmapFmt.mapCharCode(index);
            Glyph glyph = getGlyph(index);

            Shape s = getShapeFromGlyph(glyph);

            GlyphEntry ge = new GlyphEntry();
            ge.advance = (int)(getAdvance(referenceChar) * emScale * (useTwips ? SwfConstants.TWIPS_PER_PIXEL : 1));
            ge.character = c;
            ge.shape = s;

            // Glyph bounds are not used by the Flash Player so no need to calculate
	        //ge.bounds = DefineShapeBuilder.getBounds(s.shapeRecords, null);

            return ge;
        }

        public int getFirstChar()
        {
            if (platformID == PLATFORM_MICROSOFT && encodingID == ENCODING_UNDEFINED)
                return usFirstCharIndex - 0xF000;
            else
                return usFirstCharIndex;
        }

        private int getCharIndex(char index)
        {
            if (platformID == PLATFORM_MICROSOFT && encodingID == ENCODING_UNDEFINED)
                index += (usFirstCharIndex - (usFirstCharIndex - 0xF000));

            return index;
        }

        private Glyph getGlyph(int index)
        {
            Glyph glyph = null;
            GlyphDescription desc = glyf.getDescription(index);

            if (desc != null)
                glyph = new Glyph(glyf.getDescription(index), hmtx.getLeftSideBearing(index), hmtx.getAdvanceWidth(index));

            return glyph;
        }

        private Shape getShapeFromGlyph(Glyph glyph)
        {
            ShapeBuilder shape = new ShapeBuilder(useTwips);
            shape.setCurrentLineStyle(0);
            shape.setCurrentFillStyle1(1);
            shape.setUseFillStyle1(true);
            shape.processShape(new GlyphIterator(glyph, emScale, keep201Behavior));

            return shape.build();
        }

        public int getAdvance(char c)
        {
            if (hmtx != null)
            {
                int index = getCharIndex(c);
                index = cmapFmt.mapCharCode(index);
                return hmtx.getAdvanceWidth(index);
            }

            return horizAdvanceX;
        }

        public int getAscent()
        {
            return ascent;
        }

        public int getDescent()
        {
            return descent;
        }

        public String getFamily()
        {
            return fontFamily;
        }

        public int getLineGap()
        {
            return lineGap;
        }

        public int getMissingGlyphCode()
        {
            return missingGlyphCode;
        }

        public int getNumGlyphs()
        {
            return numGlyphs;
        }

        public double getPointSize()
        {
            return 1.0f;
        }

        public String getPanose()
        {
            return panose;
        }

        public short getUnitsPerEm()
        {
            return unitsPerEm;
        }

        public double getEmScale()
        {
            return emScale;
        }

	    public String getPostscriptName()
	    {
		    return postscriptName;
	    }

        private CmapFormat cmapFmt = null;
        private GlyfTable glyf;
        private HmtxTable hmtx;
        private int horizAdvanceX;

        private String fontFamily;
        private String subFamilyName;
	    private String postscriptName;
        private short unitsPerEm;
        private String panose;
        private short ascent;
        private short descent;
        private short lineGap;
        private boolean forceAscii;
        private double emScale;
        private int numGlyphs;
        private short platformID;
        private short encodingID;
        private int usFirstCharIndex;
        private int missingGlyphCode = 0;
        private boolean keep201Behavior;

    }

    public static class GlyphIterator implements ShapeIterator
    {
        private final double emScale;
        private double[][] segments;
        private int index;
        private boolean keep201Behavior;

        public GlyphIterator(Glyph glyph, double emScale, boolean keep201Behavior)
        {
            this.emScale = emScale;
            this.keep201Behavior = keep201Behavior;
            if (glyph != null)
                readPoints(glyph);
            else
                segments = new double[][]{};
//            System.out.println("Batik");
//            for (int i = 0; i < segments.length; i++)
//            {
//            	System.out.println(segments[i][4] + ": " + segments[i][0] + "  " + segments[i][1]);
//            }
        }

        private void readPoints(Glyph glyph)
        {
            int count = glyph.getPointCount();
            int offset = 0;
            boolean newContour = true;
            ArrayList<double[]> aSegments = new ArrayList<double[]>(count);
            Point lastMove = null;

            while (offset < count - 1)
            {
                Point point = glyph.getPoint(offset);

                if (point.endOfContour)
                {
                    newContour = true;
                    offset++;
                    continue;
                }

                Point point_plus1 = glyph.getPoint((offset + 1));
                Point point_plus2;

                //Implicit close, using the last move point as the next point
                if (point_plus1.endOfContour)
                    point_plus2 = lastMove;
                else if (offset <= count - 3)
                    point_plus2 = glyph.getPoint((offset + 2));
                else
                    point_plus2 = null;

                if (newContour)
                {
                    double[] segment = new double[5];
                    segment[0] = point.x * emScale;
                    segment[1] = -point.y * emScale;
                    segment[4] = MOVE_TO;
                    aSegments.add(segment);
                    newContour = false;
                    lastMove = point;
                }
                else if (point.onCurve && point_plus1 != null && point_plus1.onCurve)
                {
                    //This is a simple line
                    double[] segment = new double[5];
                    segment[0] = point_plus1.x * emScale;
                    segment[1] = -point_plus1.y * emScale;
                    segment[4] = LINE_TO;
                    aSegments.add(segment);

                    offset++;
                }
                else if (point.onCurve && !point_plus1.onCurve && point_plus2.onCurve)
                {
                    // Then draw the curve, it has no implied points
                    double[] segment = new double[5];
                    segment[0] = point_plus1.x * emScale;
                    segment[1] = -point_plus1.y * emScale;
                    segment[2] = point_plus2.x * emScale;
                    segment[3] = -point_plus2.y * emScale;
                    segment[4] = QUAD_TO;
                    aSegments.add(segment);

                    //Handle implicit close situation
                    if (point_plus1.endOfContour)
                    {
                        offset++;
                        newContour = true;
                    }
                    else
                    {
                        offset += 2;
                    }
                }
                else if (point.onCurve && !point_plus1.onCurve && !point_plus2.onCurve)
                {
                    // This is a curve with one implied point, the mid-point between the next two points
                    double[] segment = new double[5];
                    segment[0] = point_plus1.x * emScale;
                    segment[1] = -point_plus1.y * emScale;
                    segment[2] = midPoint(point_plus1.x, point_plus2.x) * emScale;
                    segment[3] = -midPoint(point_plus1.y, point_plus2.y) * emScale;
                    segment[4] = QUAD_TO;
                    aSegments.add(segment);

                    //Handle implicit close situation
                    if (point_plus1.endOfContour)
                    {
                    	offset++;
                        newContour = true;
                    }
                    else
                    {
                    	// !!! Laurie's change. Handle off-curve/off-curve/end. There is
                    	// an implict curve between the second off-curve and the starting point.

                        // Handle implicit close situation
                        if (point_plus2.endOfContour && !keep201Behavior)
                        {
    	                	segment = new double[5];
    	                    segment[0] = point_plus2.x * emScale;
    	                    segment[1] = -point_plus2.y * emScale;
    	                    segment[2] = lastMove.x * emScale;
    	                    segment[3] = -lastMove.y * emScale;
    	                    segment[4] = QUAD_TO;
    	                    aSegments.add(segment);
    	                    // !!! END Laurie's change
                        }
                        offset += 2;
                    }
                }
                else if (!point.onCurve && !point_plus1.onCurve)
                {
                    // This is a curve with two implied points, but the first one must have been the previous control point
                    double[] segment = new double[5];
                    segment[0] = point.x * emScale;
                    segment[1] = -point.y * emScale;
                    segment[2] = midPoint(point.x, point_plus1.x) * emScale;
                    segment[3] = -midPoint(point.y, point_plus1.y) * emScale;
                    segment[4] = QUAD_TO;
                    aSegments.add(segment);

//                  !!! Laurie's change. Handle off-curve/off-curve/end. There is
                	// an implict curve between the second off-curve and the starting point.

                    // Handle implicit close situation
                    if (point_plus1.endOfContour && !keep201Behavior)
                    {
	                	segment = new double[5];
	                    segment[0] = point_plus1.x * emScale;
	                    segment[1] = -point_plus1.y * emScale;
	                    segment[2] = lastMove.x * emScale;
	                    segment[3] = -lastMove.y * emScale;
	                    segment[4] = QUAD_TO;
	                    aSegments.add(segment);
	                    // !!! END Laurie's change
                    }
                    
                    offset++;
                }
                else if (!point.onCurve && point_plus1.onCurve)
                {
                    // This is a curve with one implied point, but it must have been the previous control point
                    double[] segment = new double[5];
                    segment[0] = point.x * emScale;
                    segment[1] = -point.y * emScale;
                    segment[2] = point_plus1.x * emScale;
                    segment[3] = -point_plus1.y * emScale;
                    segment[4] = QUAD_TO;
                    aSegments.add(segment);
                    offset++;
                }
                else
                {
                    //TODO: ERROR?!
                    offset++;
                }
            }

            segments = new double[aSegments.size()][];
            segments = aSegments.toArray(segments);
        }

        private static double midPoint(int a, int b)
        {
            return a + (b - a) / 2.0;
        }

        public short currentSegment(double[] coords)
        {
            coords[0] = segments[index][0];
            coords[1] = segments[index][1];
            coords[2] = segments[index][2];
            coords[3] = segments[index][3];
            return (short)segments[index][4]; //TODO: A double here is a waste of memory
        }

        public boolean isDone()
        {
            return segments == null || index >= segments.length;
        }

        public void next()
        {
            index++;
        }
    }

	public static class UnusableFontLicense extends RuntimeException
	{
        private static final long serialVersionUID = 1969620523936688562L;

        public UnusableFontLicense(String location, String description)
		{
			super("The font " + location + " has a license that prevents it from being embedded: " + description + ".");
		}
	}
}
