/*
 *
 *  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 flex2.tools;

import java.io.File;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.util.StringTokenizer;
import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Method;

import org.apache.flex.forks.batik.svggen.font.Font;
import org.apache.flex.forks.batik.svggen.font.table.Os2Table;
import org.apache.flex.forks.batik.svggen.font.table.NameTable;
import org.apache.flex.forks.batik.svggen.font.table.Table;
import flash.fonts.LocalFont;

/**
 * A tool that takes a snapshot of all font information, storing it in LocalFont objects that are serialized
 * into localFonts.ser.  This data is read in by JREFontManager.
 *
 * The fonts are found by looking at the Sun-specific APIs for finding the system font path.  If this API is
 * not available, then the system font directories can be passed in.
 *
 * This is done as a separate tool and not as part of a compilation because of speed.  Reading all of
 * the fonts on a system takes a non-trivial amount of time. 
 */
public class FontSnapshot
{
	private static Method getFontPath;
	private Map<String, LocalFont> fonts = new HashMap<String, LocalFont>();

	// for JREFontManager's initDefaultLocalFonts()
	private static boolean printForMap = true;

	public static void main(String[] args) throws Exception
	{
		FontSnapshot snapshot = new FontSnapshot(args);
		snapshot.save();
	}

	public FontSnapshot(String[] paths)
	{
		findFonts(paths);
	}

	protected void findFonts(String[] paths)
	{
		if (paths != null && paths.length != 0)
		{
			for (int i = 0; i < paths.length; i++)
			{
				findFonts(paths[i]);
			}
		}

		// FIXME: add system font dirs to FontLicenseChecker as well?
		// find the system font directories
		if (getFontPath != null)
		{
			String fPath;
			try
			{
				fPath = (String)getFontPath.invoke(null, new Object[] { Boolean.TRUE });
			}
			catch(Exception e)
			{
				throw new RuntimeException("Could not call getFontPath() for initializing system fonts: " + e, e);
			}
			StringTokenizer parser = new StringTokenizer(fPath, File.pathSeparator);
			while (parser.hasMoreTokens())
			{
				findFonts(parser.nextToken());
			}
		}
	}

	protected void findFonts(String path)
	{
		File file = new File(path);

		if (! file.exists())
		{
			throw new RuntimeException("Font or dir not found: " + file);
		}

		if (file.isDirectory())
		{
			File[] children = file.listFiles();
			if (children != null)
			{
				for (int i = 0; i < children.length; i++)
				{
					File child = children[i];
					if (child.isDirectory() || child.toString().toLowerCase().endsWith(".ttf"))
					{
						findFonts(child.toString());
					}
				}
			}
		}
		else
		{
			Font font = null;
			String err = null;
			try
			{
				font = Font.create(file.toString());
			}
			catch(Exception e)
			{
				err = e.toString();
			}

			if (font == null || font.getOS2Table() == null || font.getNameTable() == null)
			{
				System.err.println("Error reading " + file + ": " + err);
			}
			else
			{
				Os2Table os2Table = font.getOS2Table();
				int fsType = os2Table.getLicenseType();

				NameTable name = font.getNameTable();
				String copyright = name.getRecord(Table.nameCopyrightNotice);
				String trademark = name.getRecord(Table.nameTrademark);

				String postScriptName = name.getRecord(Table.namePostscriptName);
				LocalFont localFont = new LocalFont(postScriptName, path, fsType, copyright, trademark);
				LocalFont cachedFont = fonts.get(postScriptName);

				if (cachedFont != null)
				{
					if (! localFont.equals(cachedFont))
					{
						// FIXME: localize if we're keeping this class
						System.out.println("Found different fonts with the same postscript name. Keeping font " +
								postScriptName + " found at  " + cachedFont.path + " and ignoring " + localFont.path);
					}
				}
				else
				{
					fonts.put(postScriptName, localFont);

					if (printForMap)
					{
						System.out.println("defaultLocalFonts.put(\"" + postScriptName + "\", new LocalFont(\"" +
								postScriptName + "\", null, " + fsType + ", \"" + copyright + "\", \"" + trademark + "\"));");
					}
				}
			}
		}
	}

	public void save() throws IOException
	{
		if (fonts.size() == 0)
		{
			System.err.println("No fonts were found.  You must specify the system font directories.");
		}

		OutputStream buffStream = new BufferedOutputStream(new FileOutputStream("localFonts.ser"));
		ObjectOutputStream out = new ObjectOutputStream(buffStream);
		out.writeObject(fonts);
		out.flush();
		buffStream.close();
	}

	static
	{
		try
		{
			Class cls = Class.forName("sun.awt.font.NativeFontWrapper", true, Thread.currentThread().getContextClassLoader());
			//Method method = cls.getMethod("getFontPath", new Class[] { Boolean.class });
			// this is painful... don't know why do we have to do this instead of calling the commented-out call above
			Method[] meth = cls.getMethods();
			for (int i = 0; i < meth.length; i++)
			{
				Method method = meth[i];
				if (method.getName().equals("getFontPath"))
				{
					getFontPath = method;
					break;
				}
			}
		}
		catch(Exception e)
		{
			// ignore exception, not on Sun jdk 1.4 or lower

			try
			{
				Class cls = Class.forName("sun.font.FontManager", true, Thread.currentThread().getContextClassLoader());
				getFontPath = cls.getMethod("getFontPath", new Class[] { Boolean.class });
			}
			catch(Exception e2)
			{
				// ignore exception, not on Sun jdk 1.5
			}
		}

	}
}
