/*
 * Label.java
 *
 * Created on June 12, 2006, 4:21 PM
 *
 */
package usda.weru.util.table;

import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import javax.swing.ImageIcon;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; 
import org.jdom2.Element;

/**
 *
 * @author Joseph Levin
 */
public class Label implements XmlObject {

    private static final transient Logger logger = LogManager.getLogger(Label.class);

    /**
     *
     */
    protected String c_text;

    /**
     *
     */
    protected Image c_image;

    /**
     *
     */
    protected CellStyle c_cellStyle;

    /**
     *
     */
    protected WepsTableMeta c_meta;

    /**
     *
     */
    protected int c_spanRows = 0;

    /**
     *
     */
    protected int c_spanColumns = 0;

    /**
     *
     */
    protected String c_imageAngleText;

    /**
     *
     */
    protected double c_imageAngle = 0;

    /**
     *
     */
    protected Image c_rotatedImage;

    /**
     * Create a new Label and associate it with the given WepsTableMeta.
     * @param meta The WepsTableMeta this Label will belong to.
     */
    public Label(WepsTableMeta meta) {
        c_meta = meta;
        init();
    }

    private void init() {

    }

    /**
     * Load configuration information about this label from a jdom Element.
     * @param node An org.jdom2.Element containing configuration information for this Label.
     */
    @Override
    public void fromXml(Element node) {
        if (node == null) {
            return;
        }
        loadText(node);
        loadCellStyle(node);
        loadImage(node);        //Image needs to come after cell style so we cen set the renderer if needed.
        loadSpanRows(node);
        loadSpanColumns(node);
    }
    

    private void loadCellStyle(Element node) {
        Element styleNode = node.getChild(WepsTableEnum.XML_style);
        if (styleNode == null) {
            return;
        }
        String cellId = null;
        cellId = styleNode.getTextTrim();

        if (cellId != null && cellId.length() > 0) {
            c_cellStyle = c_meta.getCellStyle(cellId);
        } else {
            c_cellStyle = new CellStyle(c_meta);
            c_cellStyle.fromXml(styleNode);
        }
    }

    private void loadSpanRows(Element node) {
        String number = node.getAttributeValue(WepsTableEnum.XML_spanrows);
        try {
            c_spanRows = Integer.parseInt(number);
        } catch (NumberFormatException nfe) {
            c_spanRows = 0;
        }
    }

    private void loadSpanColumns(Element node) {
        String number = node.getAttributeValue(WepsTableEnum.XML_spancolumns);
        try {
            c_spanColumns = Integer.parseInt(number);
        } catch (NumberFormatException nfe) {
            c_spanColumns = 0;
        }
    }

    private void loadText(Element node) {
        String text = node.getChildText(WepsTableEnum.XML_text);
        if (text == null) {
            text = node.getValue();
        }
        c_text = text;
    }

    private void loadImage(Element node) {
        String imagePath = node.getChildTextTrim(WepsTableEnum.XML_image);
        if (imagePath == null || imagePath.length() == 0) {
            return;
        }
        try {
            Image image = Toolkit.getDefaultToolkit().getImage(imagePath);
            c_image = image;
            c_imageAngleText = node.getChild(WepsTableEnum.XML_image).getAttributeValue(WepsTableEnum.XML_angle);
        } catch (Exception e) {
            logger.debug("Unable to load label image.", e);
        }
    }

    /**
     * Return the number of rows this Label spans.
     * @return The number of rows.
     */
    public int getSpanRows() {
        return c_spanRows;
    }

    /**
     * Return the number of columns this Label spans.
     * @return The number of Columns.
     */
    public int getSpanColumns() {
        return c_spanColumns;
    }
    

    /**
     * Return the CellStyle used by this Label.
     * @return The CellStyle used.
     */
    public CellStyle getCellStyle() {
        return c_cellStyle;
    }

    /**
     * Return the value of the given cell.
     * @param table The WepsTable to be queried.
     * @param rowIndex The row to be queried.
     * @param columnIndex The column to be queried.
     * @return The value of the cell at [rowIndex, columnIndex].
     */
    public Object getObject(WepsTable table, int rowIndex, int columnIndex) {
        if (c_image != null) {
            //Return an image, 
            if (c_imageAngleText != null && c_imageAngleText.length() > 0) {
                //Rotate the image
                rotateImage(table, rowIndex, columnIndex);
            }
            if (c_rotatedImage != null) {
                return c_rotatedImage;
            }
            return c_image;
        } else {
            return c_text;
        }
    }

    /**
     *
     * @param table
     * @param rowIndex
     * @param columnIndex
     */
    protected void rotateImage(WepsTable table, int rowIndex, int columnIndex) {
        String angleText = table.getMeta().parse(c_imageAngleText, table, rowIndex, columnIndex).toString();
        try {
            double angle = Double.parseDouble(angleText);
            if (angle != c_imageAngle) {

                BufferedImage bimage = toBufferedImage(c_image, angle);

                c_rotatedImage = Toolkit.getDefaultToolkit().createImage(bimage.getSource());

            }
        } catch (Exception e) {
        }
    }

    /**
     * Return the text contained in this Label.
     * @return The text contained in this label.
     */
    public String getText() {
        return c_text;
    }

    // This method returns a buffered image with the contents of an image
    //Code from http://javaalmanac.com/egs/java.awt.image/Image2Buf.html?l=rel
    /**
     * Convert the supplied image to a BufferedImage.
     * @param image The Image to be converted.
     * @param rotate The amount the image needs to be rotated in degrees.
     * @return The converted image.
     */
    public static BufferedImage toBufferedImage(Image image, double rotate) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        } else if (image == null) {
            return null;
        }

        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();

        // Determine if the image has transparent pixels; for this method's
        // implementation, see e661 Determining If an Image Has Transparent Pixels
        boolean hasAlpha = hasAlpha(image);

        // Create a buffered image with a format that's compatible with the screen
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            // Determine the type of transparency of the new buffered image
            int transparency = Transparency.OPAQUE;
            if (hasAlpha) {
                transparency = Transparency.BITMASK;
            }

            // Create the buffered image
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(
                    image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }

        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            if (hasAlpha) {
                type = BufferedImage.TYPE_INT_ARGB;
            }
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }

        // Copy image to buffered image
        Graphics2D g = bimage.createGraphics();
        if (rotate != 0) {
            AffineTransform at = new AffineTransform();
            int x = bimage.getWidth() / 2;
            int y = bimage.getHeight() / 2;
            at.rotate(Math.toRadians(rotate), x, y);
            g.transform(at);
        }

        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();

        return bimage;
    }

    // This method returns true if the specified image has transparent pixels
    //Code from http://javaalmanac.com/egs/java.awt.image/HasAlpha.html
    /**
     * Check if the supplied image supports alpha.
     * @param image The image to be tested.
     * @return <b>true</b> if the image supports alpha, <b>false</b> otherwise.
     */
    public static boolean hasAlpha(Image image) {
        // If buffered image, the color model is readily available
        if (image instanceof BufferedImage) {
            BufferedImage bimage = (BufferedImage) image;
            return bimage.getColorModel().hasAlpha();
        }

        // Use a pixel grabber to retrieve the image's color model;
        // grabbing a single pixel is usually sufficient
        PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
        }

        // Get the image's color model
        ColorModel cm = pg.getColorModel();
        return cm.hasAlpha();
    }

}
