/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed 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 android.print.cts;

import static android.print.test.Utils.assertException;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintAttributes.Margins;
import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Resolution;
import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentAdapter.LayoutResultCallback;
import android.print.PrintDocumentAdapter.WriteResultCallback;
import android.print.PrintDocumentInfo;
import android.print.PrinterCapabilitiesInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.print.test.BasePrintTest;
import android.print.test.services.FirstPrintService;
import android.print.test.services.PrintServiceCallbacks;
import android.print.test.services.PrinterDiscoverySessionCallbacks;
import android.print.test.services.SecondPrintService;
import android.print.test.services.StubbablePrinterDiscoverySession;

import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * This test verifies changes to the printer capabilities are applied correctly.
 */
@RunWith(AndroidJUnit4.class)
public class PrinterCapabilitiesTest extends BasePrintTest {
    private static final String PRINTER_NAME = "Test printer";

    private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
    private static final PrintAttributes.Resolution RESOLUTION_300 =
            new PrintAttributes.Resolution("300", "300", 300, 300);
    private static final PrintAttributes.Resolution RESOLUTION_600 =
            new PrintAttributes.Resolution("600", "600", 600, 600);
    private static boolean sDefaultPrinterBeenSet;

    /**
     * That that you cannot create illegal PrinterCapabilityInfos.
     *
     * @throws Exception If anything is unexpected
     */
    @Test
    public void illegalPrinterCapabilityInfos() throws Exception {
        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
                createMockPrinterDiscoverySessionCallbacks(invocation -> {
                    StubbablePrinterDiscoverySession session =
                            ((PrinterDiscoverySessionCallbacks)
                                    invocation.getMock()).getSession();

                    PrinterId printerId = session.getService().generatePrinterId(PRINTER_NAME);

                    // printerId need to be set
                    assertException(() -> new PrinterCapabilitiesInfo.Builder(null),
                            IllegalArgumentException.class);

                    // All capability fields (beside duplex) need to be initialized:
                    // Test no color
                    assertException(() ->
                                    (new PrinterCapabilitiesInfo.Builder(printerId))
                                            .setMinMargins(DEFAULT_MARGINS)
                                            .addMediaSize(MediaSize.ISO_A4, true)
                                            .addResolution(RESOLUTION_300, true).build(),
                            IllegalStateException.class);
                    // Test bad colors
                    assertException(() ->
                                    (new PrinterCapabilitiesInfo.Builder(printerId))
                                            .setColorModes(0xffff,
                                                    PrintAttributes.COLOR_MODE_MONOCHROME),
                            IllegalArgumentException.class);
                    // Test bad duplex mode
                    assertException(() ->
                                    (new PrinterCapabilitiesInfo.Builder(printerId))
                                            .setDuplexModes(0xffff,
                                                    PrintAttributes.DUPLEX_MODE_NONE),
                            IllegalArgumentException.class);
                    // Test no mediasize
                    assertException(() ->
                                    (new PrinterCapabilitiesInfo.Builder(printerId))
                                            .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
                                                    PrintAttributes.COLOR_MODE_COLOR)
                                            .setMinMargins(DEFAULT_MARGINS)
                                            .addResolution(RESOLUTION_300, true).build(),
                            IllegalStateException.class);
                    // Test no default mediasize
                    assertException(() ->
                                    (new PrinterCapabilitiesInfo.Builder(printerId))
                                            .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
                                                    PrintAttributes.COLOR_MODE_COLOR)
                                            .setMinMargins(DEFAULT_MARGINS)
                                            .addMediaSize(MediaSize.ISO_A4, false)
                                            .addResolution(RESOLUTION_300, true).build(),
                            IllegalStateException.class);
                    // Test two default mediasizes
                    assertException(() ->
                                    (new PrinterCapabilitiesInfo.Builder(printerId))
                                            .addMediaSize(MediaSize.ISO_A4, true)
                                            .addMediaSize(MediaSize.ISO_A5, true),
                            IllegalArgumentException.class);
                    // Test no resolution
                    assertException(() ->
                                    (new PrinterCapabilitiesInfo.Builder(printerId))
                                            .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
                                                    PrintAttributes.COLOR_MODE_COLOR)
                                            .setMinMargins(DEFAULT_MARGINS)
                                            .addMediaSize(MediaSize.ISO_A4, true).build(),
                            IllegalStateException.class);
                    // Test no default resolution
                    assertException(() ->
                                    (new PrinterCapabilitiesInfo.Builder(printerId))
                                            .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
                                                    PrintAttributes.COLOR_MODE_COLOR)
                                            .setMinMargins(DEFAULT_MARGINS)
                                            .addMediaSize(MediaSize.ISO_A4, true)
                                            .addResolution(RESOLUTION_300, false).build(),
                            IllegalStateException.class);
                    // Test two default resolutions
                    assertException(() ->
                                    (new PrinterCapabilitiesInfo.Builder(printerId))
                                            .addResolution(RESOLUTION_300, true)
                                            .addResolution(RESOLUTION_600, true),
                            IllegalArgumentException.class);

                    onPrinterDiscoverySessionCreateCalled();
                    return null;
                }, null, null, null, null, null, invocation -> {
                    onPrinterDiscoverySessionDestroyCalled();
                    return null;
                });

        // Create the service callbacks for the first print service.
        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
                invocation -> firstSessionCallbacks, null, null);

        // Configure the print services.
        FirstPrintService.setCallbacks(firstServiceCallbacks);
        SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));

        PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(null, null, null);

        // Start printing.
        print(adapter);

        waitForPrinterDiscoverySessionCreateCallbackCalled();

        getActivity().finish();

        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
    }

    /**
     * That that you can use all sane legal PrinterCapabilityInfos.
     *
     * @throws Exception If anything is unexpected
     */
    @Test
    public void sanePrinterCapabilityInfos() throws Exception {
        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
                createMockPrinterDiscoverySessionCallbacks(invocation -> {
                    StubbablePrinterDiscoverySession session =
                            ((PrinterDiscoverySessionCallbacks)
                                    invocation.getMock()).getSession();

                    MediaSize[] mediaSizes = {MediaSize.ISO_A0, MediaSize.ISO_A0,
                            MediaSize.ISO_A1};
                    Resolution[] resolutions = {RESOLUTION_300, RESOLUTION_300,
                            RESOLUTION_600};
                    int[] colorModes = {PrintAttributes.COLOR_MODE_MONOCHROME,
                            PrintAttributes.COLOR_MODE_COLOR};
                    int[] duplexModes = {PrintAttributes.DUPLEX_MODE_NONE,
                            PrintAttributes.DUPLEX_MODE_LONG_EDGE,
                            PrintAttributes.DUPLEX_MODE_SHORT_EDGE};

                    ArrayList<PrinterInfo> printers = new ArrayList<>();
                    for (int mediaSizeIndex = 1; mediaSizeIndex < mediaSizes.length;
                         mediaSizeIndex++) {
                        for (int resolutionIndex = 1; resolutionIndex < mediaSizes.length;
                             resolutionIndex++) {
                            for (int colorIndex = 1; colorIndex < colorModes.length;
                                 colorIndex++) {
                                for (int duplexIndex = 1; duplexIndex < duplexModes.length;
                                     duplexIndex++) {
                                    PrinterId printerId = session.getService()
                                            .generatePrinterId(Integer.valueOf(printers.size())
                                                    .toString());

                                    // Setup capabilities
                                    PrinterCapabilitiesInfo.Builder b =
                                            new PrinterCapabilitiesInfo.Builder(printerId);

                                    for (int i = 0; i < mediaSizeIndex; i++) {
                                        b.addMediaSize(mediaSizes[i], i == mediaSizeIndex - 1);
                                    }

                                    for (int i = 0; i < resolutionIndex; i++) {
                                        b.addResolution(resolutions[i],
                                                i == resolutionIndex - 1);
                                    }

                                    int allColors = 0;
                                    for (int i = 0; i < colorIndex; i++) {
                                        allColors |= colorModes[i];
                                    }
                                    b.setColorModes(allColors, colorModes[colorIndex - 1]);

                                    int allDuplexModes = 0;
                                    for (int i = 0; i < duplexIndex; i++) {
                                        allDuplexModes |= duplexModes[i];
                                    }
                                    b.setDuplexModes(allDuplexModes,
                                            duplexModes[duplexIndex - 1]);

                                    b.setMinMargins(DEFAULT_MARGINS);

                                    // Create printer
                                    PrinterInfo printer = (new PrinterInfo.Builder(printerId,
                                            Integer.valueOf(printers.size()).toString(),
                                            PrinterInfo.STATUS_IDLE)).setCapabilities(b.build())
                                            .build();

                                    // Verify capabilities
                                    PrinterCapabilitiesInfo cap = printer.getCapabilities();

                                    assertEquals(mediaSizeIndex, cap.getMediaSizes().size());
                                    assertEquals(mediaSizes[mediaSizeIndex - 1],
                                            cap.getDefaults().getMediaSize());
                                    for (int i = 0; i < mediaSizeIndex; i++) {
                                        assertTrue(cap.getMediaSizes().contains(mediaSizes[i]));
                                    }

                                    assertEquals(resolutionIndex, cap.getResolutions().size());
                                    assertEquals(resolutions[resolutionIndex - 1],
                                            cap.getDefaults().getResolution());
                                    for (int i = 0; i < resolutionIndex; i++) {
                                        assertTrue(cap.getResolutions().contains(resolutions[i]));
                                    }

                                    assertEquals(allColors, cap.getColorModes());
                                    assertEquals(colorModes[colorIndex - 1],
                                            cap.getDefaults().getColorMode());

                                    assertEquals(allDuplexModes, cap.getDuplexModes());
                                    assertEquals(duplexModes[duplexIndex - 1],
                                            cap.getDefaults().getDuplexMode());

                                    assertEquals(DEFAULT_MARGINS, cap.getMinMargins());

                                    // Add printer
                                    printers.add(printer);
                                }
                            }
                        }
                    }

                    session.addPrinters(printers);

                    onPrinterDiscoverySessionCreateCalled();
                    return null;
                }, null, null, null, null, null, invocation -> {
                    onPrinterDiscoverySessionDestroyCalled();
                    return null;
                });

        // Create the service callbacks for the first print service.
        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
                invocation -> firstSessionCallbacks, null, null);

        // Configure the print services.
        FirstPrintService.setCallbacks(firstServiceCallbacks);
        SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));

        PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(null, null, null);

        // Start printing.
        print(adapter);

        waitForPrinterDiscoverySessionCreateCallbackCalled();

        getUiDevice().pressBack();

        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
    }

    /**
     * Base test that performs a print operation with a give PrinterCapabilityInfo and run a test
     * function before finishing.
     *
     * @throws Exception
     */
    private void testPrinterCapabilityInfo(final Function<PrinterId, PrinterCapabilitiesInfo>
            capBuilder, Consumer<PrintAttributes> test) throws Exception {
        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
                createMockPrinterDiscoverySessionCallbacks(invocation -> {
                    StubbablePrinterDiscoverySession session =
                            ((PrinterDiscoverySessionCallbacks)
                                    invocation.getMock()).getSession();

                    PrinterId printerId = session.getService()
                            .generatePrinterId(PRINTER_NAME);

                    ArrayList<PrinterInfo> printers = new ArrayList<>();
                    printers.add((new PrinterInfo.Builder(printerId, PRINTER_NAME,
                            PrinterInfo.STATUS_IDLE))
                            .setCapabilities(capBuilder.apply(printerId)).build());

                    session.addPrinters(printers);

                    onPrinterDiscoverySessionCreateCalled();
                    return null;
                }, null, null, null, null, null, invocation -> {
                    onPrinterDiscoverySessionDestroyCalled();
                    return null;
                });

        // Create the service callbacks for the first print service.
        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
                invocation -> firstSessionCallbacks, null, null);

        // Configure the print services.
        FirstPrintService.setCallbacks(firstServiceCallbacks);
        SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));

        final PrintAttributes[] layoutAttributes = new PrintAttributes[1];

        PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
                invocation -> {
                    LayoutResultCallback callback = (LayoutResultCallback) invocation
                            .getArguments()[3];
                    PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
                            .setPageCount(1)
                            .build();
                    layoutAttributes[0] = (PrintAttributes) invocation.getArguments()[1];

                    callback.onLayoutFinished(info, true);
                    return null;
                },
                invocation -> {
                    Object[] args = invocation.getArguments();
                    PageRange[] pages = (PageRange[]) args[0];
                    ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
                    WriteResultCallback callback = (WriteResultCallback) args[3];

                    writeBlankPages(layoutAttributes[0], fd, pages[0].getStart(),
                            pages[0].getEnd());
                    fd.close();

                    callback.onWriteFinished(pages);
                    return null;
                }, null);

        // Start printing.
        print(adapter);

        // make sure that options does not crash
        openPrintOptions();

        if (!sDefaultPrinterBeenSet) {
            // Select printer under test
            selectPrinter(PRINTER_NAME);
        }

        clickPrintButton();

        if (!sDefaultPrinterBeenSet) {
            answerPrintServicesWarning(true);
            sDefaultPrinterBeenSet = true;
        }

        test.accept(layoutAttributes[0]);

        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
    }

    /**
     * That that you use a default color that is not in the allowed colors. This is allowed because
     * of historical reasons.
     *
     * @throws Exception If anything is unexpected
     */
    @Test
    public void invalidDefaultColor() throws Exception {
        testPrinterCapabilityInfo(
                (printerId) -> (new PrinterCapabilitiesInfo.Builder(printerId))
                        .addMediaSize(MediaSize.ISO_A4, true)
                        .addResolution(RESOLUTION_300, true)
                        .setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME,
                                PrintAttributes.COLOR_MODE_COLOR).build(),
                (layoutAttributes) -> assertEquals(layoutAttributes.getColorMode(),
                        PrintAttributes.COLOR_MODE_MONOCHROME));
    }

    /**
     * That that you use a default duplex mode that is not in the allowed duplex modes. This is
     * allowed because of historical reasons.
     *
     * @throws Exception If anything is unexpected
     */
    @Test
    public void invalidDefaultDuplexMode() throws Exception {
        testPrinterCapabilityInfo(
                (printerId) -> (new PrinterCapabilitiesInfo.Builder(printerId))
                        .addMediaSize(MediaSize.ISO_A4, true)
                        .addResolution(RESOLUTION_300, true)
                        .setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME,
                                PrintAttributes.COLOR_MODE_MONOCHROME)
                        .setDuplexModes(PrintAttributes.DUPLEX_MODE_LONG_EDGE
                                | PrintAttributes.DUPLEX_MODE_NONE,
                                PrintAttributes.DUPLEX_MODE_SHORT_EDGE).build(),
                (layoutAttributes) -> assertTrue(layoutAttributes.getDuplexMode() ==
                        PrintAttributes.DUPLEX_MODE_LONG_EDGE || layoutAttributes.getDuplexMode() ==
                        PrintAttributes.DUPLEX_MODE_NONE));
    }
}
