/* ====================================================================
   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.hwmf.usermodel;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.poi.hwmf.draw.HwmfGraphics;
import org.apache.poi.hwmf.record.HwmfHeader;
import org.apache.poi.hwmf.record.HwmfPlaceableHeader;
import org.apache.poi.hwmf.record.HwmfRecord;
import org.apache.poi.hwmf.record.HwmfRecordType;
import org.apache.poi.hwmf.record.HwmfWindowing.WmfSetWindowExt;
import org.apache.poi.hwmf.record.HwmfWindowing.WmfSetWindowOrg;
import org.apache.poi.util.LittleEndianInputStream;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;

public class HwmfPicture {
    private static final POILogger logger = POILogFactory.getLogger(HwmfPicture.class);
    
    final List<HwmfRecord> records = new ArrayList<HwmfRecord>();
    final HwmfPlaceableHeader placeableHeader;
    final HwmfHeader header;
    
    public HwmfPicture(InputStream inputStream) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(inputStream, 10000);
        LittleEndianInputStream leis = new LittleEndianInputStream(bis);
        placeableHeader = HwmfPlaceableHeader.readHeader(leis);
        header = new HwmfHeader(leis);
        
        for (;;) {
            if (leis.available() < 6) {
                logger.log(POILogger.ERROR, "unexpected eof - wmf file was truncated");
                break;
            }
            // recordSize in DWORDs
            long recordSize = leis.readUInt()*2;
            int recordFunction = leis.readShort();
            // 4 bytes (recordSize) + 2 bytes (recordFunction)
            int consumedSize = 6;
            HwmfRecordType wrt = HwmfRecordType.getById(recordFunction);
            if (wrt == null) {
                throw new IOException("unexpected record type: "+recordFunction);
            }
            if (wrt == HwmfRecordType.eof) break;
            if (wrt.clazz == null) {
                throw new IOException("unsupported record type: "+recordFunction);
            }
            
            HwmfRecord wr;
            try {
                wr = wrt.clazz.newInstance();
                records.add(wr);
            } catch (Exception e) {
                throw (IOException)new IOException("can't create wmf record").initCause(e);
            }
            
            consumedSize += wr.init(leis, recordSize, recordFunction);
            int remainingSize = (int)(recordSize - consumedSize);
            assert(remainingSize >= 0);
            if (remainingSize > 0) {
            	// skip size in loops, because not always all bytes are skipped in one call 
                for (int i=remainingSize; i>0; i-=leis.skip(i));
            }
        }
    }

    public List<HwmfRecord> getRecords() {
        return Collections.unmodifiableList(records);
    }

    public void draw(Graphics2D ctx) {
        Dimension dim = getSize();
        int width = Units.pointsToPixel(dim.getWidth());
        // keep aspect ratio for height
        int height = Units.pointsToPixel(dim.getHeight());
        Rectangle2D bounds = new Rectangle2D.Double(0,0,width,height);
        draw(ctx, bounds);
    }
    
    public void draw(Graphics2D ctx, Rectangle2D graphicsBounds) {
        AffineTransform at = ctx.getTransform();
        try {
            Rectangle2D wmfBounds = getBounds();
            // scale output bounds to image bounds
            ctx.translate(graphicsBounds.getX(), graphicsBounds.getY());
            ctx.scale(graphicsBounds.getWidth()/wmfBounds.getWidth(), graphicsBounds.getHeight()/wmfBounds.getHeight());
            
            HwmfGraphics g = new HwmfGraphics(ctx, wmfBounds);
            for (HwmfRecord r : records) {
                r.draw(g);
            }
        } finally {
            ctx.setTransform(at);
        }
    }

    /**
     * Returns the bounding box in device-independent units. Usually this is taken from the placeable header.
     * 
     * @return the bounding box
     */
    public Rectangle2D getBounds() {
        if (placeableHeader != null) {
            return placeableHeader.getBounds();
        } else {
            WmfSetWindowOrg wOrg = null;
            WmfSetWindowExt wExt = null;
            for (HwmfRecord r : getRecords()) {
                if (wOrg != null && wExt != null) {
                    break;
                }
                if (r instanceof WmfSetWindowOrg) {
                    wOrg = (WmfSetWindowOrg)r;
                } else if (r instanceof WmfSetWindowExt) {
                    wExt = (WmfSetWindowExt)r;
                }
            }
            if (wOrg == null || wExt == null) {
                throw new RuntimeException("invalid wmf file - window records are incomplete.");
            }
            return new Rectangle2D.Double(wOrg.getX(), wOrg.getY(), wExt.getWidth(), wExt.getHeight());
        }        
    }
    
    public HwmfPlaceableHeader getPlaceableHeader() {
        return placeableHeader;
    }

    public HwmfHeader getHeader() {
        return header;
    }
    
    /**
     * Return the image size in points
     *
     * @return the image size in points
     */
    public Dimension getSize() {
        double inch = (placeableHeader == null) ? 1440 : placeableHeader.getUnitsPerInch();
        Rectangle2D bounds = getBounds();
        
        //coefficient to translate from WMF dpi to 72dpi
        double coeff = Units.POINT_DPI/inch;
        return new Dimension((int)Math.round(bounds.getWidth()*coeff), (int)Math.round(bounds.getHeight()*coeff));
    }
}
