/*
 * Copyright 2015 Datalogics, Inc.
 */

package com.datalogics.pdf.samples.printing;

import static com.datalogics.pdf.samples.util.Matchers.bufferedImageHasChecksum;

import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;

import com.datalogics.pdf.samples.SampleTest;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import mockit.Mock;
import mockit.MockUp;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.awt.image.BufferedImage;
import java.awt.print.PrinterException;
import java.awt.print.PrinterIOException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;

/**
 * Tests the PrintPdf sample.
 */
@SuppressFBWarnings(value = { "SIC_INNER_SHOULD_BE_STATIC_ANON", "UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS" },
                    justification = "JMockit coding pattern depends on anonymous classes "
                                    + "and methods with no discernable call site")
public class PrintPdfTest extends SampleTest {
    private static final String RENDERED_IMAGE_NAME = "renderedImage_page%d.png";
    private static final String[] PAGE_IMAGE_CHECKSUMS = { "897ac162b0ab9e798771250ca8fdd7997f03cbd1",
        "f2e86261405b8e6e1a1d94f9f67571d4a8f7fef6" };
    private static final String DEFAULT_INPUT = "pdfjavatoolkit-ds.pdf";

    @Rule
    public ExpectedException expected = ExpectedException.none();

    @Test
    public <T extends PrinterJob> void testMain() throws Exception {
        assumeThat("This test requires a Java 7 JRE for the checksums to work",
                   System.getProperty("java.runtime.version"), startsWith("1.7."));
        // Mock the PrintServiceLookup.lookupDefaultPrintService() method to return a TestPrintService object
        new MockUp<PrintServiceLookup>() {
            @Mock(invocations = 1)
            PrintService lookupDefaultPrintService() {
                return new FakePrintService();
            }
        };

        // Mock the PrinterJob.getPrinterJob() method to return a TestPrinterJob object
        new MockUp<T>() {
            @Mock(invocations = 1)
            public PrinterJob getPrinterJob() {
                return new TestPrinterJob();
            }
        };

        // Call the main method
        final URL inputUrl = PrintPdf.class.getResource(DEFAULT_INPUT);
        PrintPdf.printPdf(inputUrl);
    }

    @Test
    public void testMainNoPrinter() throws Exception {
        // Mock the PrinterServiceLookup.lookupDefaultPrintService() method to return nothing (no printer available)
        new MockUp<PrintServiceLookup>() {
            @Mock(invocations = 1)
            PrintService lookupDefaultPrintService() {
                return null;
            }
        };

        // Call the main method
        expected.expect(PrinterException.class);
        expected.expectMessage("Printer failed to exist.");
        final URL inputUrl = PrintPdf.class.getResource(DEFAULT_INPUT);
        PrintPdf.printPdf(inputUrl);
    }

    /*
     * TestPrinterJob implements a 'fake' PrinterJob to intercept print requests.
     */
    private static class TestPrinterJob extends FakePrinterJob {
        @Override
        public void processPageImage(final BufferedImage image, final int pageIndex) throws PrinterIOException {
            savePageImage(image, pageIndex);
            assertThat(image, bufferedImageHasChecksum(PAGE_IMAGE_CHECKSUMS[pageIndex]));
        }

        // Based on a code snippet from the Java tutorials:
        // https://docs.oracle.com/javase/tutorial/2d/images/saveimage.html
        private void savePageImage(final BufferedImage image, final int pageIndex) throws PrinterIOException {
            final String outputName = String.format(RENDERED_IMAGE_NAME, pageIndex);
            final File outputFile = newOutputFile(outputName);
            try {
                ImageIO.write(image, "png", outputFile);
            } catch (final IOException ioe) {
                throw new PrinterIOException(ioe);
            }
        }
    }
}

@@ -1678,20 +1678,24 @@
 oid test
-Main
+PrintPdf
 () throw
@@ -2468,36 +2468,40 @@
     // Call the 
-main
+printPdf
  method%0A        
@@ -2610,32 +2610,42 @@
    %7D%0A%0A    @Test%0A
+    @Test%0A
     public void 
@@ -2652,12 +2652,16 @@
 test
-Main
+PrintPdf
 NoPr
@@ -3016,12 +3016,16 @@
 the 
-main
+printPdf
  met

Rename method names.