/*
 * Copyright (C) 2014 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 com.android.printspooler.renderer;

import android.app.Service;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.pdf.PdfEditor;
import android.graphics.pdf.PdfRenderer;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintAttributes.Margins;
import android.util.Log;
import android.view.View;
import com.android.printspooler.util.PageRangeUtils;
import libcore.io.IoUtils;
import com.android.printspooler.util.BitmapSerializeUtils;
import java.io.IOException;

/**
 * Service for manipulation of PDF documents in an isolated process.
 */
public final class PdfManipulationService extends Service {
    public static final String ACTION_GET_RENDERER =
            "com.android.printspooler.renderer.ACTION_GET_RENDERER";
    public static final String ACTION_GET_EDITOR =
            "com.android.printspooler.renderer.ACTION_GET_EDITOR";

    public static final int ERROR_MALFORMED_PDF_FILE = -2;

    public static final int ERROR_SECURE_PDF_FILE = -3;

    private static final String LOG_TAG = "PdfManipulationService";
    private static final boolean DEBUG = false;

    private static final int MILS_PER_INCH = 1000;
    private static final int POINTS_IN_INCH = 72;

    @Override
    public IBinder onBind(Intent intent) {
        String action = intent.getAction();
        switch (action) {
            case ACTION_GET_RENDERER: {
                return new PdfRendererImpl();
            }
            case ACTION_GET_EDITOR: {
                return new PdfEditorImpl();
            }
            default: {
                throw new IllegalArgumentException("Invalid intent action:" + action);
            }
        }
    }

    private final class PdfRendererImpl extends IPdfRenderer.Stub {
        private final Object mLock = new Object();

        private Bitmap mBitmap;
        private PdfRenderer mRenderer;

        @Override
        public int openDocument(ParcelFileDescriptor source) throws RemoteException {
            synchronized (mLock) {
                try {
                    throwIfOpened();
                    if (DEBUG) {
                        Log.i(LOG_TAG, "openDocument()");
                    }
                    mRenderer = new PdfRenderer(source);
                    return mRenderer.getPageCount();
                } catch (IOException | IllegalStateException e) {
                    IoUtils.closeQuietly(source);
                    Log.e(LOG_TAG, "Cannot open file", e);
                    return ERROR_MALFORMED_PDF_FILE;
                } catch (SecurityException e) {
                    IoUtils.closeQuietly(source);
                    Log.e(LOG_TAG, "Cannot open file", e);
                    return ERROR_SECURE_PDF_FILE;
                }
            }
        }

        @Override
        public void renderPage(int pageIndex, int bitmapWidth, int bitmapHeight,
                PrintAttributes attributes, ParcelFileDescriptor destination) {
            synchronized (mLock) {
                try {
                    throwIfNotOpened();

                    try (PdfRenderer.Page page = mRenderer.openPage(pageIndex)) {
                        final int srcWidthPts = page.getWidth();
                        final int srcHeightPts = page.getHeight();

                        final int dstWidthPts = pointsFromMils(
                                attributes.getMediaSize().getWidthMils());
                        final int dstHeightPts = pointsFromMils(
                                attributes.getMediaSize().getHeightMils());

                        final boolean scaleContent = mRenderer.shouldScaleForPrinting();
                        final boolean contentLandscape = !attributes.getMediaSize().isPortrait();

                        final float displayScale;
                        Matrix matrix = new Matrix();

                        if (scaleContent) {
                            displayScale = Math.min((float) bitmapWidth / srcWidthPts,
                                    (float) bitmapHeight / srcHeightPts);
                        } else {
                            if (contentLandscape) {
                                displayScale = (float) bitmapHeight / dstHeightPts;
                            } else {
                                displayScale = (float) bitmapWidth / dstWidthPts;
                            }
                        }
                        matrix.postScale(displayScale, displayScale);

                        Configuration configuration = PdfManipulationService.this.getResources()
                                .getConfiguration();
                        if (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
                            matrix.postTranslate(bitmapWidth - srcWidthPts * displayScale, 0);
                        }

                        Margins minMargins = attributes.getMinMargins();
                        final int paddingLeftPts = pointsFromMils(minMargins.getLeftMils());
                        final int paddingTopPts = pointsFromMils(minMargins.getTopMils());
                        final int paddingRightPts = pointsFromMils(minMargins.getRightMils());
                        final int paddingBottomPts = pointsFromMils(minMargins.getBottomMils());

                        Rect clip = new Rect();
                        clip.left = (int) (paddingLeftPts * displayScale);
                        clip.top = (int) (paddingTopPts * displayScale);
                        clip.right = (int) (bitmapWidth - paddingRightPts * displayScale);
                        clip.bottom = (int) (bitmapHeight - paddingBottomPts * displayScale);

                        if (DEBUG) {
                            Log.i(LOG_TAG, "Rendering page:" + pageIndex);
                        }

                        Bitmap bitmap = getBitmapForSize(bitmapWidth, bitmapHeight);
                        page.render(bitmap, clip, matrix, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);

                        BitmapSerializeUtils.writeBitmapPixels(bitmap, destination);
                    }
                } catch (Throwable e) {
                    Log.e(LOG_TAG, "Cannot render page", e);

                    // The error is propagated to the caller when it tries to read the bitmap and
                    // the pipe is closed prematurely
                } finally {
                    IoUtils.closeQuietly(destination);
                }
            }
        }

        @Override
        public void closeDocument() {
            synchronized (mLock) {
                throwIfNotOpened();
                if (DEBUG) {
                    Log.i(LOG_TAG, "closeDocument()");
                }
                mRenderer.close();
                mRenderer = null;
            }
        }

        private Bitmap getBitmapForSize(int width, int height) {
            if (mBitmap != null) {
                if (mBitmap.getWidth() == width && mBitmap.getHeight() == height) {
                    mBitmap.eraseColor(Color.WHITE);
                    return mBitmap;
                }
                mBitmap.recycle();
            }
            mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            mBitmap.eraseColor(Color.WHITE);
            return mBitmap;
        }

        private void throwIfOpened() {
            if (mRenderer != null) {
                throw new IllegalStateException("Already opened");
            }
        }

        private void throwIfNotOpened() {
            if (mRenderer == null) {
                throw new IllegalStateException("Not opened");
            }
        }
    }

    private final class PdfEditorImpl extends IPdfEditor.Stub {
        private final Object mLock = new Object();

        private PdfEditor mEditor;

        @Override
        public int openDocument(ParcelFileDescriptor source) throws RemoteException {
            synchronized (mLock) {
                try {
                    throwIfOpened();
                    if (DEBUG) {
                        Log.i(LOG_TAG, "openDocument()");
                    }
                    mEditor = new PdfEditor(source);
                    return mEditor.getPageCount();
                } catch (IOException | IllegalStateException e) {
                    IoUtils.closeQuietly(source);
                    Log.e(LOG_TAG, "Cannot open file", e);
                    throw new RemoteException(e.toString());
                }
            }
        }

        @Override
        public void removePages(PageRange[] ranges) {
            synchronized (mLock) {
                throwIfNotOpened();
                if (DEBUG) {
                    Log.i(LOG_TAG, "removePages()");
                }

                ranges = PageRangeUtils.normalize(ranges);

                int lastPageIdx = mEditor.getPageCount() - 1;

                final int rangeCount = ranges.length;
                for (int i = rangeCount - 1; i >= 0; i--) {
                    PageRange range = ranges[i];

                    // Ignore removal of pages that are outside the document
                    if (range.getEnd() > lastPageIdx) {
                        if (range.getStart() > lastPageIdx) {
                            continue;
                        }
                        range = new PageRange(range.getStart(), lastPageIdx);
                    }

                    for (int j = range.getEnd(); j >= range.getStart(); j--) {
                        mEditor.removePage(j);
                    }
                }
            }
        }

        @Override
        public void applyPrintAttributes(PrintAttributes attributes) {
            synchronized (mLock) {
                throwIfNotOpened();
                if (DEBUG) {
                    Log.i(LOG_TAG, "applyPrintAttributes()");
                }

                Rect mediaBox = new Rect();
                Rect cropBox = new Rect();
                Matrix transform = new Matrix();

                final boolean layoutDirectionRtl = getResources().getConfiguration()
                        .getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;

                // We do not want to rotate the media box, so take into account orientation.
                final int dstWidthPts = pointsFromMils(attributes.getMediaSize().getWidthMils());
                final int dstHeightPts = pointsFromMils(attributes.getMediaSize().getHeightMils());

                final boolean scaleForPrinting = mEditor.shouldScaleForPrinting();

                final int pageCount = mEditor.getPageCount();
                for (int i = 0; i < pageCount; i++) {
                    if (!mEditor.getPageMediaBox(i, mediaBox)) {
                        Log.e(LOG_TAG, "Malformed PDF file");
                        return;
                    }

                    final int srcWidthPts = mediaBox.width();
                    final int srcHeightPts = mediaBox.height();

                    // Update the media box with the desired size.
                    mediaBox.right = dstWidthPts;
                    mediaBox.bottom = dstHeightPts;
                    mEditor.setPageMediaBox(i, mediaBox);

                    // Make sure content is top-left after media box resize.
                    transform.setTranslate(0, srcHeightPts - dstHeightPts);

                    // Scale the content if document allows it.
                    final float scale;
                    if (scaleForPrinting) {
                        scale = Math.min((float) dstWidthPts / srcWidthPts,
                                (float) dstHeightPts / srcHeightPts);
                        transform.postScale(scale, scale);
                    } else {
                        scale = 1.0f;
                    }

                    // Update the crop box relatively to the media box change, if needed.
                    if (mEditor.getPageCropBox(i, cropBox)) {
                        cropBox.left = (int) (cropBox.left * scale + 0.5f);
                        cropBox.top = (int) (cropBox.top * scale + 0.5f);
                        cropBox.right = (int) (cropBox.right * scale + 0.5f);
                        cropBox.bottom = (int) (cropBox.bottom * scale + 0.5f);
                        cropBox.intersect(mediaBox);
                        mEditor.setPageCropBox(i, cropBox);
                    }

                    // If in RTL mode put the content in the logical top-right corner.
                    if (layoutDirectionRtl) {
                        final float dx = dstWidthPts - (int) (srcWidthPts * scale + 0.5f);
                        final float dy = 0;
                        transform.postTranslate(dx, dy);
                    }

                    // Adjust the physical margins if needed.
                    Margins minMargins = attributes.getMinMargins();
                    final int paddingLeftPts = pointsFromMils(minMargins.getLeftMils());
                    final int paddingTopPts = pointsFromMils(minMargins.getTopMils());
                    final int paddingRightPts = pointsFromMils(minMargins.getRightMils());
                    final int paddingBottomPts = pointsFromMils(minMargins.getBottomMils());

                    Rect clip = new Rect(mediaBox);
                    clip.left += paddingLeftPts;
                    clip.top += paddingTopPts;
                    clip.right -= paddingRightPts;
                    clip.bottom -= paddingBottomPts;

                    // Apply the accumulated transforms.
                    mEditor.setTransformAndClip(i, transform, clip);
                }
            }
        }

        @Override
        public void write(ParcelFileDescriptor destination) throws RemoteException {
            synchronized (mLock) {
                try {
                    throwIfNotOpened();
                    if (DEBUG) {
                        Log.i(LOG_TAG, "write()");
                    }
                    mEditor.write(destination);
                } catch (IOException | IllegalStateException e) {
                    IoUtils.closeQuietly(destination);
                    Log.e(LOG_TAG, "Error writing PDF to file.", e);
                    throw new RemoteException(e.toString());
                }
            }
        }

        @Override
        public void closeDocument() {
            synchronized (mLock) {
                throwIfNotOpened();
                if (DEBUG) {
                    Log.i(LOG_TAG, "closeDocument()");
                }
                mEditor.close();
                mEditor = null;
            }
        }

        private void throwIfOpened() {
            if (mEditor != null) {
                throw new IllegalStateException("Already opened");
            }
        }

        private void throwIfNotOpened() {
            if (mEditor == null) {
                throw new IllegalStateException("Not opened");
            }
        }
    }

    private static int pointsFromMils(int mils) {
        return (int) (((float) mils / MILS_PER_INCH) * POINTS_IN_INCH);
    }
}
