/*
 * 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 contentPortrait = attributes.getMediaSize().isPortrait();

                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 = contentPortrait
                        ? pointsFromMils(attributes.getMediaSize().getWidthMils())
                        : pointsFromMils(attributes.getMediaSize().getHeightMils());
                final int dstHeightPts = contentPortrait
                        ? pointsFromMils(attributes.getMediaSize().getHeightMils())
                        : pointsFromMils(attributes.getMediaSize().getWidthMils());

                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);

                    // Rotate the content if in landscape.
                    if (!contentPortrait) {
                        transform.postRotate(270);
                        transform.postTranslate(0, dstHeightPts);
                    }

                    // Scale the content if document allows it.
                    final float scale;
                    if (scaleForPrinting) {
                        if (contentPortrait) {
                            scale = Math.min((float) dstWidthPts / srcWidthPts,
                                    (float) dstHeightPts / srcHeightPts);
                            transform.postScale(scale, scale);
                        } else {
                            scale = Math.min((float) dstWidthPts / srcHeightPts,
                                    (float) dstHeightPts / srcWidthPts);
                            transform.postScale(scale, scale, mediaBox.left, mediaBox.bottom);
                        }
                    } 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 = contentPortrait
                                ? dstWidthPts - (int) (srcWidthPts * scale + 0.5f) : 0;
                        final float dy = contentPortrait
                                ? 0 : - (dstHeightPts - (int) (srcWidthPts * scale + 0.5f));
                        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);
    }
}
