package com.srbenoit.font;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.srbenoit.log.LoggedObject;

/**
 * A class to render some text.
 */
public class FontRender extends LoggedObject {

    /** the path of the font to load */
    private static final String PATH = "/cygwin/home/Steve Benoit/pace.ttf";

    /** a test string to print at small font size */
    private static final String TEST1 = "The quick brown fox jumps over the lazy dog.";

    /** the panel */
    private final transient FontRenderPanel panel;

    /** the font to render */
    private transient Font font;

    /**
     * Constructs a new <code>FontRender</code>.
     */
    public FontRender() {

        InputStream input;

        this.panel = new FontRenderPanel(this);
        this.panel.setPreferredSize(new Dimension(600, 600));
        this.panel.setBackground(Color.WHITE);

        try {
            input = new FileInputStream(PATH);

            try {
                this.font = Font.createFont(Font.TRUETYPE_FONT, input);
                input.close();
            } catch (Exception exc1) {
                LOG.warning("Failed to read " + PATH + ": " + exc1.getLocalizedMessage());
                this.font = new Font("Dialog", Font.PLAIN, 9);
            }
        } catch (Exception exc2) {
            LOG.warning("Failed to open " + PATH + ": " + exc2.getLocalizedMessage());
            this.font = new Font("Dialog", Font.PLAIN, 9);
        }
    }

    /**
     * Gets the panel.
     *
     * @return  the panel
     */
    public JPanel getPanel() {

        return this.panel;
    }

    /**
     * Gets the font.
     *
     * @return  the font
     */
    public Font getFont() {

        return this.font;
    }

    /**
     * Main method to create the panel and show it.
     *
     * @param  args  command-line arguments
     */
    public static void main(final String... args) {

        JFrame frame;

        frame = new JFrame("Render Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new FontRender().getPanel());
        frame.pack();
        frame.setLocation(600, 50);
        frame.setVisible(true);
    }

    /**
     * The panel.
     */
    private static class FontRenderPanel extends JPanel {

        /** version number for serialization */
        private static final long serialVersionUID = 50159041185573735L;

        /** the owning <code>FontRender</code> object */
        private final FontRender owner;

        /**
         * Constructs a new <code>FontRenderPanel</code>.
         *
         * @param  owningFontRender  the owning <code>FontRender</code> object
         */
        protected FontRenderPanel(final FontRender owningFontRender) {

            this.owner = owningFontRender;
        }

        /**
         * Renders the panel.
         *
         * @param  grx  the <code>Graphics</code> to which to render
         */
        @Override public void paintComponent(final Graphics grx) {

            Graphics2D g2d;
            Font[] fonts;
            Object[] modes;
            String[] labels;
            int height;
            int yPos;

            g2d = (Graphics2D) grx;

            super.paintComponent(grx);

            // Gather the font sizes to use
            fonts = new Font[4];
            fonts[0] = this.owner.getFont().deriveFont(30.0f);
            fonts[1] = this.owner.getFont().deriveFont(20.0f);
            fonts[2] = this.owner.getFont().deriveFont(10.0f);
            fonts[3] = this.owner.getFont().deriveFont(8.0f);

            // Gather the rendering modes to use and their labels
            modes = new Object[7];
            labels = new String[7];

            modes[0] = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
            modes[1] = RenderingHints.VALUE_TEXT_ANTIALIAS_ON;
            modes[2] = RenderingHints.VALUE_TEXT_ANTIALIAS_GASP;
            modes[3] = RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR;
            modes[4] = RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB;
            modes[5] = RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR;
            modes[6] = RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB;

            labels[0] = "Normal";
            labels[1] = "Antialias";
            labels[2] = "Gasp";
            labels[3] = "HBGR";
            labels[4] = "HRGB";
            labels[5] = "VBGR";
            labels[6] = "VRGB";

            height = grx.getFontMetrics(fonts[0]).getHeight();
            yPos = height;

            for (int i = 0; i < modes.length; i++) {
                g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, modes[i]);
                drawTestString(g2d, fonts, labels[i], yPos);
                yPos += height;
            }

            g2d.setFont(fonts[fonts.length - 1]);
            height = g2d.getFontMetrics().getHeight();

            for (int i = 0; i < modes.length; i++) {
                g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, modes[i]);

                g2d.drawString("This is a test of font rendering at eight points (" + labels[i]
                    + ")", 10, yPos);
                yPos += height;
            }

            g2d.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST, Integer.valueOf(100));
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);

            for (int i = 0; i < fonts.length; i++) {

                g2d.setFont(fonts[i]);
                yPos += g2d.getFontMetrics().getAscent();
                g2d.drawString("!\"#$%&'()*+,-./ (Using HRGB)", 10, yPos);
                yPos += g2d.getFontMetrics().getDescent();
                yPos += g2d.getFontMetrics().getLeading();
            }
        }

        /**
         * Draws a test string in all font sizes.
         *
         * @param  g2d    the <code>Graphics2D</code> to which to draw
         * @param  fonts  the list of fonts to use to draw the string
         * @param  str    the string to draw
         * @param  yPos   the Y position at which to draw
         */
        private void drawTestString(final Graphics2D g2d, final Font[] fonts, final String str,
            final int yPos) {

            int xPos = 10;

            for (int i = 0; i < fonts.length; i++) {
                g2d.setFont(fonts[i]);
                g2d.drawString(str, xPos, yPos);
                xPos += 150;
            }

            g2d.drawString(TEST1, xPos, yPos);
        }
    }
}
