/*
 * Copyright (C) 2013 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.printservice;

import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
import android.print.PrinterCapabilitiesInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.util.ArrayMap;
import android.util.Log;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * This class encapsulates the interaction between a print service and the
 * system during printer discovery. During printer discovery you are responsible
 * for adding discovered printers, removing previously added printers that
 * disappeared, and updating already added printers.
 * <p>
 * During the lifetime of this session you may be asked to start and stop
 * performing printer discovery multiple times. You will receive a call to {@link
 * PrinterDiscoverySession#onStartPrinterDiscovery(List)} to start printer
 * discovery and a call to {@link PrinterDiscoverySession#onStopPrinterDiscovery()}
 * to stop printer discovery. When the system is no longer interested in printers
 * discovered by this session you will receive a call to {@link #onDestroy()} at
 * which point the system will no longer call into the session and all the session
 * methods will do nothing.
 * </p>
 * <p>
 * Discovered printers are added by invoking {@link
 * PrinterDiscoverySession#addPrinters(List)}. Added printers that disappeared are
 * removed by invoking {@link PrinterDiscoverySession#removePrinters(List)}. Added
 * printers whose properties or capabilities changed are updated through a call to
 * {@link PrinterDiscoverySession#addPrinters(List)}. The printers added in this
 * session can be acquired via {@link #getPrinters()} where the returned printers
 * will be an up-to-date snapshot of the printers that you reported during the
 * session. Printers are <strong>not</strong> persisted across sessions.
 * </p>
 * <p>
 * The system will make a call to {@link #onValidatePrinters(List)} if you
 * need to update some printers. It is possible that you add a printer without
 * specifying its capabilities. This enables you to avoid querying all discovered
 * printers for their capabilities, rather querying the capabilities of a printer
 * only if necessary. For example, the system will request that you update a printer
 * if it gets selected by the user. When validating printers you do not need to
 * provide the printers' capabilities but may do so.
 * </p>
 * <p>
 * If the system is interested in being constantly updated for the state of a
 * printer you will receive a call to {@link #onStartPrinterStateTracking(PrinterId)}
 * after which you will have to do a best effort to keep the system updated for
 * changes in the printer state and capabilities. You also <strong>must</strong>
 * update the printer capabilities if you did not provide them when adding it, or
 * the printer will be ignored. When the system is no longer interested in getting
 * updates for a printer you will receive a call to {@link #onStopPrinterStateTracking(
 * PrinterId)}.
 * </p>
 * <p>
 * <strong>Note: </strong> All callbacks in this class are executed on the main
 * application thread. You also have to invoke any method of this class on the main
 * application thread.
 * </p>
 */
public abstract class PrinterDiscoverySession {
    private static final String LOG_TAG = "PrinterDiscoverySession";

    private static int sIdCounter = 0;

    private final int mId;

    private final ArrayMap<PrinterId, PrinterInfo> mPrinters =
            new ArrayMap<PrinterId, PrinterInfo>();

    private final List<PrinterId> mTrackedPrinters =
            new ArrayList<PrinterId>();

    private ArrayMap<PrinterId, PrinterInfo> mLastSentPrinters;

    private IPrintServiceClient mObserver;

    private boolean mIsDestroyed;

    private boolean mIsDiscoveryStarted;

    /**
     * Constructor.
     */
    public PrinterDiscoverySession() {
        mId = sIdCounter++;
    }

    void setObserver(IPrintServiceClient observer) {
        mObserver = observer;
        // If some printers were added in the method that
        // created the session, send them over.
        if (!mPrinters.isEmpty()) {
            try {
                mObserver.onPrintersAdded(new ParceledListSlice<PrinterInfo>(getPrinters()));
            } catch (RemoteException re) {
                Log.e(LOG_TAG, "Error sending added printers", re);
            }
        }
    }

    int getId() {
        return mId;
    }

    /**
     * Gets the printers reported in this session. For example, if you add two
     * printers and remove one of them, the returned list will contain only
     * the printer that was added but not removed.
     * <p>
     * <strong>Note: </strong> Calls to this method after the session is
     * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
     * </p>
     *
     * @return The printers.
     *
     * @see #addPrinters(List)
     * @see #removePrinters(List)
     * @see #isDestroyed()
     */
    public final List<PrinterInfo> getPrinters() {
        PrintService.throwIfNotCalledOnMainThread();
        if (mIsDestroyed) {
            return Collections.emptyList();
        }
        return new ArrayList<PrinterInfo>(mPrinters.values());
    }

    /**
     * Adds discovered printers. Adding an already added printer updates it.
     * Removed printers can be added again. You can call this method multiple
     * times during the life of this session. Duplicates will be ignored.
     * <p>
     * <strong>Note: </strong> Calls to this method after the session is
     * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
     * </p>
     *
     * @param printers The printers to add.
     *
     * @see #removePrinters(List)
     * @see #getPrinters()
     * @see #isDestroyed()
     */
    public final void addPrinters(List<PrinterInfo> printers) {
        PrintService.throwIfNotCalledOnMainThread();

        // If the session is destroyed - nothing do to.
        if (mIsDestroyed) {
            Log.w(LOG_TAG, "Not adding printers - session destroyed.");
            return;
        }

        if (mIsDiscoveryStarted) {
            // If during discovery, add the new printers and send them.
            List<PrinterInfo> addedPrinters = null;
            final int addedPrinterCount = printers.size();
            for (int i = 0; i < addedPrinterCount; i++) {
                PrinterInfo addedPrinter = printers.get(i);
                PrinterInfo oldPrinter = mPrinters.put(addedPrinter.getId(), addedPrinter);
                if (oldPrinter == null || !oldPrinter.equals(addedPrinter)) {
                    if (addedPrinters == null) {
                        addedPrinters = new ArrayList<PrinterInfo>();
                    }
                    addedPrinters.add(addedPrinter);
                }
            }

            // Send the added printers, if such.
            if (addedPrinters != null) {
                try {
                    mObserver.onPrintersAdded(new ParceledListSlice<PrinterInfo>(addedPrinters));
                } catch (RemoteException re) {
                    Log.e(LOG_TAG, "Error sending added printers", re);
                }
            }
        } else {
            // Remember the last sent printers if needed.
            if (mLastSentPrinters == null) {
                mLastSentPrinters = new ArrayMap<PrinterId, PrinterInfo>(mPrinters);
            }

            // Update the printers.
            final int addedPrinterCount = printers.size();
            for (int i = 0; i < addedPrinterCount; i++) {
                PrinterInfo addedPrinter = printers.get(i);
                if (mPrinters.get(addedPrinter.getId()) == null) {
                    mPrinters.put(addedPrinter.getId(), addedPrinter);
                }
            }
        }
    }

    /**
     * Removes added printers. Removing an already removed or never added
     * printer has no effect. Removed printers can be added again. You can
     * call this method multiple times during the lifetime of this session.
     * <p>
     * <strong>Note: </strong> Calls to this method after the session is
     * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
     * </p>
     *
     * @param printerIds The ids of the removed printers.
     *
     * @see #addPrinters(List)
     * @see #getPrinters()
     * @see #isDestroyed()
     */
    public final void removePrinters(List<PrinterId> printerIds) {
        PrintService.throwIfNotCalledOnMainThread();

        // If the session is destroyed - nothing do to.
        if (mIsDestroyed) {
            Log.w(LOG_TAG, "Not removing printers - session destroyed.");
            return;
        }

        if (mIsDiscoveryStarted) {
            // If during discovery, remove existing printers and send them.
            List<PrinterId> removedPrinterIds = new ArrayList<PrinterId>();
            final int removedPrinterIdCount = printerIds.size();
            for (int i = 0; i < removedPrinterIdCount; i++) {
                PrinterId removedPrinterId = printerIds.get(i);
                if (mPrinters.remove(removedPrinterId) != null) {
                    removedPrinterIds.add(removedPrinterId);
                }
            }

            // Send the removed printers, if such.
            if (!removedPrinterIds.isEmpty()) {
                try {
                    mObserver.onPrintersRemoved(new ParceledListSlice<PrinterId>(
                            removedPrinterIds));
                } catch (RemoteException re) {
                    Log.e(LOG_TAG, "Error sending removed printers", re);
                }
            }
        } else {
            // Remember the last sent printers if needed.
            if (mLastSentPrinters == null) {
                mLastSentPrinters = new ArrayMap<PrinterId, PrinterInfo>(mPrinters);
            }

            // Update the printers.
            final int removedPrinterIdCount = printerIds.size();
            for (int i = 0; i < removedPrinterIdCount; i++) {
                PrinterId removedPrinterId = printerIds.get(i);
                mPrinters.remove(removedPrinterId);
            }
        }
    }

    private void sendOutOfDiscoveryPeriodPrinterChanges() {
        // Noting changed since the last discovery period - nothing to do.
        if (mLastSentPrinters == null || mLastSentPrinters.isEmpty()) {
            mLastSentPrinters = null;
            return;
        }

        // Determine the added printers.
        List<PrinterInfo> addedPrinters = null;
        for (PrinterInfo printer : mPrinters.values()) {
            PrinterInfo sentPrinter = mLastSentPrinters.get(printer.getId());
            if (sentPrinter == null || !sentPrinter.equals(printer)) {
                if (addedPrinters == null) {
                    addedPrinters = new ArrayList<PrinterInfo>();
                }
                addedPrinters.add(printer);
            }
        }

        // Send the added printers, if such.
        if (addedPrinters != null) {
            try {
                mObserver.onPrintersAdded(new ParceledListSlice<PrinterInfo>(addedPrinters));
            } catch (RemoteException re) {
                Log.e(LOG_TAG, "Error sending added printers", re);
            }
        }

        // Determine the removed printers.
        List<PrinterId> removedPrinterIds = null;
        for (PrinterInfo sentPrinter : mLastSentPrinters.values()) {
            if (!mPrinters.containsKey(sentPrinter.getId())) {
                if (removedPrinterIds == null) {
                    removedPrinterIds = new ArrayList<PrinterId>();
                }
                removedPrinterIds.add(sentPrinter.getId());
            }
        }

        // Send the removed printers, if such.
        if (removedPrinterIds != null) {
            try {
                mObserver.onPrintersRemoved(new ParceledListSlice<PrinterId>(removedPrinterIds));
            } catch (RemoteException re) {
                Log.e(LOG_TAG, "Error sending removed printers", re);
            }
        }

        mLastSentPrinters = null;
    }

    /**
     * Callback asking you to start printer discovery. Discovered printers should be
     * added via calling {@link #addPrinters(List)}. Added printers that disappeared
     * should be removed via calling {@link #removePrinters(List)}. Added printers
     * whose properties or capabilities changed should be updated via calling {@link
     * #addPrinters(List)}. You will receive a call to {@link #onStopPrinterDiscovery()}
     * when you should stop printer discovery.
     * <p>
     * During the lifetime of this session all printers that are known to your print
     * service have to be added. The system does not retain any printers across sessions.
     * However, if you were asked to start and then stop performing printer discovery
     * in this session, then a subsequent discovering should not re-discover already
     * discovered printers. You can get the printers reported during this session by
     * calling {@link #getPrinters()}.
     * </p>
     * <p>
     * <strong>Note: </strong>You are also given a list of printers whose availability
     * has to be checked first. For example, these printers could be the user's favorite
     * ones, therefore they have to be verified first. You do <strong>not need</strong>
     * to provide the capabilities of the printers, rather verify whether they exist
     * similarly to {@link #onValidatePrinters(List)}.
     * </p>
     *
     * @param priorityList The list of printers to validate first. Never null.
     *
     * @see #onStopPrinterDiscovery()
     * @see #addPrinters(List)
     * @see #removePrinters(List)
     * @see #isPrinterDiscoveryStarted()
     */
    public abstract void onStartPrinterDiscovery(List<PrinterId> priorityList);

    /**
     * Callback notifying you that you should stop printer discovery.
     *
     * @see #onStartPrinterDiscovery(List)
     * @see #isPrinterDiscoveryStarted()
     */
    public abstract void onStopPrinterDiscovery();

    /**
     * Callback asking you to validate that the given printers are valid, that
     * is they exist. You are responsible for checking whether these printers
     * exist and for the ones that do exist notify the system via calling
     * {@link #addPrinters(List)}.
     * <p>
     * <strong>Note: </strong> You are <strong>not required</strong> to provide
     * the printer capabilities when updating the printers that do exist.
     * <p>
     *
     * @param printerIds The printers to validate.
     *
     * @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo)
     *      PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo)
     */
    public abstract void onValidatePrinters(List<PrinterId> printerIds);

    /**
     * Callback asking you to start tracking the state of a printer. Tracking
     * the state means that you should do a best effort to observe the state
     * of this printer and notify the system if that state changes via calling
     * {@link #addPrinters(List)}.
     * <p>
     * <strong>Note: </strong> A printer can be initially added without its
     * capabilities to avoid polling printers that the user will not select.
     * However, after this method is called you are expected to update the
     * printer <strong>including</strong> its capabilities. Otherwise, the
     * printer will be ignored.
     * <p>
     * <p>
     * A scenario when you may be requested to track a printer's state is if
     * the user selects that printer and the system has to present print
     * options UI based on the printer's capabilities. In this case the user
     * should be promptly informed if, for example, the printer becomes
     * unavailable.
     * </p>
     *
     * @param printerId The printer to start tracking.
     *
     * @see #onStopPrinterStateTracking(PrinterId)
     * @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo)
     *      PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo)
     */
    public abstract void onStartPrinterStateTracking(PrinterId printerId);

    /**
     * Callback asking you to stop tracking the state of a printer. The passed
     * in printer id is the one for which you received a call to {@link
     * #onStartPrinterStateTracking(PrinterId)}.
     *
     * @param printerId The printer to stop tracking.
     *
     * @see #onStartPrinterStateTracking(PrinterId)
     */
    public abstract void onStopPrinterStateTracking(PrinterId printerId);

    /**
     * Gets the printers that should be tracked. These are printers that are
     * important to the user and for which you received a call to {@link
     * #onStartPrinterStateTracking(PrinterId)} asking you to observer their
     * state and reporting it to the system via {@link #addPrinters(List)}.
     * You will receive a call to {@link #onStopPrinterStateTracking(PrinterId)}
     * if you should stop tracking a printer.
     * <p>
     * <strong>Note: </strong> Calls to this method after the session is
     * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
     * </p>
     *
     * @return The printers.
     *
     * @see #onStartPrinterStateTracking(PrinterId)
     * @see #onStopPrinterStateTracking(PrinterId)
     * @see #isDestroyed()
     */
    public final List<PrinterId> getTrackedPrinters() {
        PrintService.throwIfNotCalledOnMainThread();
        if (mIsDestroyed) {
            return Collections.emptyList();
        }
        return new ArrayList<PrinterId>(mTrackedPrinters);
    }

    /**
     * Notifies you that the session is destroyed. After this callback is invoked
     * any calls to the methods of this class will be ignored, {@link #isDestroyed()}
     * will return true and you will also no longer receive callbacks.
     *
     * @see #isDestroyed()
     */
    public abstract void onDestroy();

    /**
     * Gets whether the session is destroyed.
     *
     * @return Whether the session is destroyed.
     *
     * @see #onDestroy()
     */
    public final boolean isDestroyed() {
        PrintService.throwIfNotCalledOnMainThread();
        return mIsDestroyed;
    }

    /**
     * Gets whether printer discovery is started.
     *
     * @return Whether printer discovery is destroyed.
     *
     * @see #onStartPrinterDiscovery(List)
     * @see #onStopPrinterDiscovery()
     */
    public final boolean isPrinterDiscoveryStarted() {
        PrintService.throwIfNotCalledOnMainThread();
        return mIsDiscoveryStarted;
    }

    void startPrinterDiscovery(List<PrinterId> priorityList) {
        if (!mIsDestroyed) {
            mIsDiscoveryStarted = true;
            sendOutOfDiscoveryPeriodPrinterChanges();
            if (priorityList == null) {
                priorityList = Collections.emptyList();
            }
            onStartPrinterDiscovery(priorityList);
        }
    }

    void stopPrinterDiscovery() {
        if (!mIsDestroyed) {
            mIsDiscoveryStarted = false;
            onStopPrinterDiscovery();
        }
    }

    void validatePrinters(List<PrinterId> printerIds) {
        if (!mIsDestroyed && mObserver != null) {
            onValidatePrinters(printerIds);
        }
    }

    void startPrinterStateTracking(PrinterId printerId) {
        if (!mIsDestroyed && mObserver != null
                && !mTrackedPrinters.contains(printerId)) {
            mTrackedPrinters.add(printerId);
            onStartPrinterStateTracking(printerId);
        }
    }

    void stopPrinterStateTracking(PrinterId printerId) {
        if (!mIsDestroyed && mObserver != null
                && mTrackedPrinters.remove(printerId)) {
            onStopPrinterStateTracking(printerId);
        }
    }

    void destroy() {
        if (!mIsDestroyed) {
            mIsDestroyed = true;
            mIsDiscoveryStarted = false;
            mPrinters.clear();
            mLastSentPrinters = null;
            mObserver = null;
            onDestroy();
        }
    }
}
