/*
 * 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.batik.test.svg;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.batik.ext.awt.image.GraphicsUtil;
import org.apache.batik.ext.awt.image.renderable.Filter;
import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
import org.apache.batik.ext.awt.image.spi.ImageWriter;
import org.apache.batik.ext.awt.image.spi.ImageWriterRegistry;
import org.apache.batik.test.AbstractTest;
import org.apache.batik.test.TestReport;
import org.apache.batik.util.ParsedURL;

/**
 * This test does a pixel comparison of two images and passes if the 
 * two images are identical. It fails otherwise, producing a report
 * describing why the two images are different.
 *
 * @author <a href="mailto:vhardy@apache.org">Vincent Hardy</a>
 * @version $Id$
 */
public class ImageCompareTest extends AbstractTest {
    public static final String ERROR_COULD_NOT_OPEN_IMAGE
        = "ImageCompareTest.error.could.not.open.image";

    public static final String ERROR_COULD_NOT_LOAD_IMAGE
        = "ImageCompareTest.error.could.not.load.image";

    public static final String ERROR_DIFFERENCES
        = "ImageCompareTest.error.differences";

    public static final String ERROR_WHILE_COMPARING_FILES
        = "ImageCompareTest.error.while.comparing.files";

    public static final String ENTRY_KEY_FIRST_IMAGE
        = "ImageCompareTest.entry.key.first.image";

    public static final String ENTRY_KEY_SECOND_IMAGE
        = "ImageCompareTest.entry.key.second.image";

    public static final String ENTRY_KEY_COMPARISON
        = "ImageCompareTest.entry.key.comparison";
    
    public static final String ENTRY_KEY_DIFFERENCE
        = "ImageCompareTest.entry.key.difference";

    public static final String ENTRY_KEY_IMAGE_URL
        = "ImageCompareTest.entry.key.image.url";

    public static final String IMAGE_TYPE_DIFFERENCE
        = "_diff";

    public static final String IMAGE_TYPE_COMPARISON
        = "_cmp";

    /**
     * Prefix for the temporary files created by Tests
     * of this class
     */
    public static final String TEMP_FILE_PREFIX 
        = "ImageCompareTest";

    /**
     * Suffix for the temporary files created by 
     * Tests of this class
     */
    public static final String TEMP_FILE_SUFFIX
        = "";

    /**
     * URL for the first image to be compared.
     */
    protected String urlAStr;
    protected URL urlA;
    
    /**
     * URL for the second image to be compared
     */
    protected String urlBStr;
    protected URL urlB;

    /**
     * Resolves the input string as follows.
     * + First, the string is interpreted as a file description.
     *   If the file exists, then the file name is turned into
     *   a URL.
     * + Otherwise, the string is supposed to be a URL. If it
     *   is an invalid URL, an IllegalArgumentException is thrown.
     */
    protected URL resolveURL(String url){
        // Is url a file?
        File f = (new File(url)).getAbsoluteFile();
        if(f.exists()){
            try{
                return f.toURI().toURL();
            }catch(MalformedURLException e){
                throw new IllegalArgumentException();
            }
        }
        
        // url is not a file. It must be a regular URL...
        try{
            return new URL(url);
        }catch(MalformedURLException e){
            throw new IllegalArgumentException(url);
        }
    }

    /**
     * This test makes a binary comparison of the two images
     * (and not a pixel comparison). If the images are different,
     * the test generates a report containing the two images and
     * a delta images to help the user visualize the difference.
     *
     * @param urlA first image
     * @param urlB second image
     */
    public ImageCompareTest(String urlA,
                            String urlB){
        urlAStr = urlA;
        urlBStr = urlB;
    }

    protected void initURLs(){
        if(urlA == null){
            throw new IllegalArgumentException();
        }
        
        if(urlB == null){
            throw new IllegalArgumentException();
        }

        this.urlA = resolveURL(urlAStr);
        this.urlB = resolveURL(urlBStr);
    }

    public TestReport rumImpl() throws Exception {
        initURLs();

        InputStream streamA = null;

        try{
            streamA = new BufferedInputStream(urlA.openStream());
        }catch(IOException e){
            return reportException(ERROR_COULD_NOT_OPEN_IMAGE, e);
        }

        InputStream streamB = null;

        try{
            streamB = new BufferedInputStream(urlB.openStream());
        }catch(IOException e){
            return reportException(ERROR_COULD_NOT_OPEN_IMAGE, e);
        }

        boolean accurate = false;

        try{
            accurate = compare(streamA, streamB);
        }catch(IOException e){
            TestReport report = reportException(ERROR_WHILE_COMPARING_FILES, e);
            report.addDescriptionEntry(ENTRY_KEY_FIRST_IMAGE,
                                       urlA.toString());
            report.addDescriptionEntry(ENTRY_KEY_SECOND_IMAGE,
                                       urlB.toString());
            return report;
        }

        if(accurate){
            return reportSuccess();
        }

        // We are in error (images are different: produce an image
        // with the two images side by side as well as a diff image)
        BufferedImage imageA = getImage(urlA);
        if(imageA == null){
            TestReport report = reportError(ERROR_COULD_NOT_LOAD_IMAGE);
            report.addDescriptionEntry(ENTRY_KEY_IMAGE_URL,
                                       urlA.toString());
            return report;
        }

        BufferedImage imageB = getImage(urlB);
        if(imageB == null){
            TestReport report = reportError(ERROR_COULD_NOT_LOAD_IMAGE);
            report.addDescriptionEntry(ENTRY_KEY_IMAGE_URL,
                                       urlB.toString());
            return report;
        }

        BufferedImage diff = buildDiffImage(imageA, imageB);
        BufferedImage cmp  = buildCompareImage(imageA, imageB);

        File tmpDiff = imageToFile(diff, IMAGE_TYPE_DIFFERENCE);
        File tmpCmp  = imageToFile(cmp,  IMAGE_TYPE_COMPARISON);

        TestReport report = reportError(ERROR_DIFFERENCES);
        report.addDescriptionEntry(ENTRY_KEY_COMPARISON, tmpCmp);
        report.addDescriptionEntry(ENTRY_KEY_DIFFERENCE, tmpDiff);

        return report;
    }

    protected BufferedImage buildCompareImage(BufferedImage ref,
                                              BufferedImage gen){
        BufferedImage cmp = new BufferedImage(ref.getWidth()*2,
                                              ref.getHeight(),
                                              BufferedImage.TYPE_INT_ARGB);

        Graphics2D g = cmp.createGraphics();
        g.setPaint(Color.white);
        g.fillRect(0, 0, cmp.getWidth(), cmp.getHeight());
        g.drawImage(ref, 0, 0, null);
        g.translate(ref.getWidth(), 0);
        g.drawImage(gen, 0, 0, null);
        g.dispose();

        return cmp;
    }

    /**
     * Creates a temporary File into which the input image is
     * saved.
     */
    protected File imageToFile(BufferedImage img,
                               String imageType)
        throws IOException {

        File imageFile =  makeRandomFileName(imageType);
        imageFile.deleteOnExit();

        ImageWriter writer = ImageWriterRegistry.getInstance()
            .getWriterFor("image/png");
        OutputStream out = new FileOutputStream(imageFile);
        try {
            writer.writeImage(img, out);
        } finally {
            out.close();
        }
        
        return imageFile;
        
    }

    /**
     * Creates a temporary File into which the input image is
     * saved.
     */
    protected File makeRandomFileName(String imageType)
        throws IOException {
        
        return File.createTempFile(TEMP_FILE_PREFIX,
                                   TEMP_FILE_SUFFIX + imageType,
                                   null);
    }
    
    /**
     * Builds a new BufferedImage that is the difference between the two input images
     */
    public static BufferedImage buildDiffImage(BufferedImage ref,
                                               BufferedImage gen) {
        BufferedImage diff = new BufferedImage(ref.getWidth(),
                                               ref.getHeight(),
                                               BufferedImage.TYPE_INT_ARGB);
        WritableRaster refWR = ref.getRaster();
        WritableRaster genWR = gen.getRaster();
        WritableRaster dstWR = diff.getRaster();

        boolean refPre = ref.isAlphaPremultiplied();
        if (!refPre) {
            ColorModel     cm = ref.getColorModel();
            cm = GraphicsUtil.coerceData(refWR, cm, true);
            ref = new BufferedImage(cm, refWR, true, null);
        }
        boolean genPre = gen.isAlphaPremultiplied();
        if (!genPre) {
            ColorModel     cm = gen.getColorModel();
            cm = GraphicsUtil.coerceData(genWR, cm, true);
            gen = new BufferedImage(cm, genWR, true, null);
        }


        int w=ref.getWidth();
        int h=ref.getHeight();

        int y, i,val;
        int [] refPix = null;
        int [] genPix = null;
        for (y=0; y<h; y++) {
            refPix = refWR.getPixels  (0, y, w, 1, refPix);
            genPix = genWR.getPixels  (0, y, w, 1, genPix);
            for (i=0; i<refPix.length; i++) {
                // val = ((genPix[i]-refPix[i])*5)+128;
                val = ((refPix[i]-genPix[i])*10)+128;
                if ((val & 0xFFFFFF00) != 0)
                    if ((val & 0x80000000) != 0) val = 0;
                    else                         val = 255;
                genPix[i] = val;
            }
            dstWR.setPixels(0, y, w, 1, genPix);
        }

        if (!genPre) {
            ColorModel cm = gen.getColorModel();
            cm = GraphicsUtil.coerceData(genWR, cm, false);
        }
        
        if (!refPre) {
            ColorModel cm = ref.getColorModel();
            cm = GraphicsUtil.coerceData(refWR, cm, false);
        }

        return diff;
    }


    /**
     * Compare the two input streams
     */
    public static boolean compare(InputStream refStream,
                                  InputStream newStream)
        throws IOException{
        int b, nb;
        do {
            b = refStream.read();
            nb = newStream.read();
        } while (b != -1 && nb != -1 && b == nb);
        refStream.close();
        newStream.close();
        return (b == nb);
    }

    /**
     * Loads an image from a URL
     */
    protected BufferedImage getImage(URL url) {
        ImageTagRegistry reg = ImageTagRegistry.getRegistry();
        Filter filt = reg.readURL(new ParsedURL(url));
        if(filt == null){
            return null;
        }

        RenderedImage red = filt.createDefaultRendering();
        if(red == null){
            return null;
        }
        
        BufferedImage img = new BufferedImage(red.getWidth(),
                                              red.getHeight(),
                                              BufferedImage.TYPE_INT_ARGB);
        red.copyData(img.getRaster());

        return img;
    }


}

