/* ====================================================================
   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 org.apache.poi.ss.util;

import static org.apache.poi.util.Units.EMU_PER_PIXEL;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * @author Yegor Kozlov
 */
public class ImageUtils {
    private static final POILogger logger = POILogFactory.getLogger(ImageUtils.class);

    public static final int PIXEL_DPI = 96;

    /**
     * Return the dimension of this image
     *
     * @param is the stream containing the image data
     * @param type type of the picture: {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_JPEG},
     * {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_PNG} or {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_DIB}
     *
     * @return image dimension in pixels
     */
    public static Dimension getImageDimension(InputStream is, int type){
        Dimension size = new Dimension();

        switch (type){
            //we can calculate the preferred size only for JPEG, PNG and BMP
            //other formats like WMF, EMF and PICT are not supported in Java
            case Workbook.PICTURE_TYPE_JPEG:
            case Workbook.PICTURE_TYPE_PNG:
            case Workbook.PICTURE_TYPE_DIB:
                try {
                    //read the image using javax.imageio.*
                    ImageInputStream iis = ImageIO.createImageInputStream( is );
                    try {
                        Iterator<ImageReader> i = ImageIO.getImageReaders( iis );
                        ImageReader r = i.next();
                        try {
                            r.setInput( iis );
                            BufferedImage img = r.read(0);
        
                            int[] dpi = getResolution(r);
        
                            //if DPI is zero then assume standard 96 DPI
                            //since cannot divide by zero
                            if (dpi[0] == 0) dpi[0] = PIXEL_DPI;
                            if (dpi[1] == 0) dpi[1] = PIXEL_DPI;
        
                            size.width = img.getWidth()*PIXEL_DPI/dpi[0];
                            size.height = img.getHeight()*PIXEL_DPI/dpi[1];
                        } finally {
                            r.dispose();
                        }
                    } finally {
                        iis.close();
                    }

                } catch (IOException e) {
                    //silently return if ImageIO failed to read the image
                    logger.log(POILogger.WARN, e);
                }

                break;
            default:
                logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized");
        }
        return size;
    }

    /**
     * The metadata of PNG and JPEG can contain the width of a pixel in millimeters.
     * Return the the "effective" dpi calculated as <code>25.4/HorizontalPixelSize</code>
     * and <code>25.4/VerticalPixelSize</code>.  Where 25.4 is the number of mm in inch.
     *
     * @return array of two elements: <code>{horisontalPdi, verticalDpi}</code>.
     * {96, 96} is the default.
     */
    public static int[] getResolution(ImageReader r) throws IOException {
        int hdpi=96, vdpi=96;
        double mm2inch = 25.4;

        NodeList lst;
        Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0");
        lst = node.getElementsByTagName("HorizontalPixelSize");
        if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value")));

        lst = node.getElementsByTagName("VerticalPixelSize");
        if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value")));

        return new int[]{hdpi, vdpi};
    }

    /**
     * Calculate and set the preferred size (anchor) for this picture.
     *
     * @param scaleX the amount by which image width is multiplied relative to the original width.
     * @param scaleY the amount by which image height is multiplied relative to the original height.
     * @return the new Dimensions of the scaled picture in EMUs
     */
    public static Dimension setPreferredSize(Picture picture, double scaleX, double scaleY){
        ClientAnchor anchor = picture.getClientAnchor();
        boolean isHSSF = (anchor instanceof HSSFClientAnchor);
        PictureData data = picture.getPictureData();
        Sheet sheet = picture.getSheet();
        
        // in pixel
        Dimension imgSize = getImageDimension(new ByteArrayInputStream(data.getData()), data.getPictureType());
        // in emus
        Dimension anchorSize = ImageUtils.getDimensionFromAnchor(picture);
        final double scaledWidth = (scaleX == Double.MAX_VALUE)
            ? imgSize.getWidth() : anchorSize.getWidth()/EMU_PER_PIXEL * scaleX;
        final double scaledHeight = (scaleY == Double.MAX_VALUE)
            ? imgSize.getHeight() : anchorSize.getHeight()/EMU_PER_PIXEL * scaleY;

        double w = 0;
        int col2 = anchor.getCol1();
        int dx2 = 0;

        //space in the leftmost cell
        w = sheet.getColumnWidthInPixels(col2++);
        if (isHSSF) {
            w *= 1d - anchor.getDx1()/1024d;
        } else {
            w -= anchor.getDx1()/(double)EMU_PER_PIXEL;
        }
        
        while(w < scaledWidth){
            w += sheet.getColumnWidthInPixels(col2++);
        }
        
        if(w > scaledWidth) {
            //calculate dx2, offset in the rightmost cell
            double cw = sheet.getColumnWidthInPixels(--col2);
            double delta = w - scaledWidth;
            if (isHSSF) {
                dx2 = (int)((cw-delta)/cw*1024);
            } else {
                dx2 = (int)((cw-delta)*EMU_PER_PIXEL);
            }
            if (dx2 < 0) dx2 = 0;
        }
        anchor.setCol2(col2);
        anchor.setDx2(dx2);

        double h = 0;
        int row2 = anchor.getRow1();
        int dy2 = 0;
        
        h = getRowHeightInPixels(sheet,row2++);
        if (isHSSF) {
            h *= 1 - anchor.getDy1()/256d;
        } else {
            h -= anchor.getDy1()/(double)EMU_PER_PIXEL;
        }

        while(h < scaledHeight){
            h += getRowHeightInPixels(sheet,row2++);
        }
        
        if(h > scaledHeight) {
            double ch = getRowHeightInPixels(sheet,--row2);
            double delta = h - scaledHeight;
            if (isHSSF) {
                dy2 = (int)((ch-delta)/ch*256);
            } else {
                dy2 = (int)((ch-delta)*EMU_PER_PIXEL);
            }
            if (dy2 < 0) dy2 = 0;
        }

        anchor.setRow2(row2);
        anchor.setDy2(dy2);

        Dimension dim = new Dimension(
            (int)Math.round(scaledWidth*EMU_PER_PIXEL),
            (int)Math.round(scaledHeight*EMU_PER_PIXEL)
        );
        
        return dim;
    }

    /**
     * Calculates the dimensions in EMUs for the anchor of the given picture
     *
     * @param picture the picture containing the anchor
     * @return the dimensions in EMUs
     */
    public static Dimension getDimensionFromAnchor(Picture picture) {
        ClientAnchor anchor = picture.getClientAnchor();
        boolean isHSSF = (anchor instanceof HSSFClientAnchor);
        Sheet sheet = picture.getSheet();

        double w = 0;
        int col2 = anchor.getCol1();

        //space in the leftmost cell
        w = sheet.getColumnWidthInPixels(col2++);
        if (isHSSF) {
            w *= 1 - anchor.getDx1()/1024d;
        } else {
            w -= anchor.getDx1()/(double)EMU_PER_PIXEL;
        }
        
        while(col2 < anchor.getCol2()){
            w += sheet.getColumnWidthInPixels(col2++);
        }
        
        if (isHSSF) {
            w += sheet.getColumnWidthInPixels(col2) * anchor.getDx2()/1024d;
        } else {
            w += anchor.getDx2()/(double)EMU_PER_PIXEL;
        }

        double h = 0;
        int row2 = anchor.getRow1();
        
        h = getRowHeightInPixels(sheet,row2++);
        if (isHSSF) {
            h *= 1 - anchor.getDy1()/256d;
        } else {
            h -= anchor.getDy1()/(double)EMU_PER_PIXEL;
        }

        while(row2 < anchor.getRow2()){
            h += getRowHeightInPixels(sheet,row2++);
        }
        
        if (isHSSF) {
            h += getRowHeightInPixels(sheet,row2) * anchor.getDy2()/256;
        } else {
            h += anchor.getDy2()/(double)EMU_PER_PIXEL;
        }

        w *= EMU_PER_PIXEL;
        h *= EMU_PER_PIXEL;
        
        return new Dimension((int)Math.rint(w), (int)Math.rint(h));
    }
    
    
    public static double getRowHeightInPixels(Sheet sheet, int rowNum) {
        Row r = sheet.getRow(rowNum);
        double points = (r == null) ? sheet.getDefaultRowHeightInPoints() : r.getHeightInPoints();
        return Units.toEMU(points)/(double)EMU_PER_PIXEL;
    }
}
