/*
 * 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.ui;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Margins;
import android.print.PrintDocumentInfo;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
import com.android.internal.os.SomeArgs;
import com.android.printspooler.R;
import com.android.printspooler.model.MutexFileProvider;
import com.android.printspooler.widget.PrintContentView;
import com.android.printspooler.widget.EmbeddedContentContainer;
import com.android.printspooler.widget.PrintOptionsLayout;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallback,
        PageAdapter.PreviewArea, EmbeddedContentContainer.OnSizeChangeListener {

    private final PrintActivity mActivity;

    private final MutexFileProvider mFileProvider;
    private final MyHandler mHandler;

    private final PageAdapter mPageAdapter;
    private final StaggeredGridLayoutManager mLayoutManger;

    private final PrintOptionsLayout mPrintOptionsLayout;
    private final RecyclerView mRecyclerView;
    private final PrintContentView mContentView;
    private final EmbeddedContentContainer mEmbeddedContentContainer;

    private final PreloadController mPreloadController;

    private int mDocumentPageCount;

    public PrintPreviewController(PrintActivity activity, MutexFileProvider fileProvider) {
        mActivity = activity;
        mHandler = new MyHandler(activity.getMainLooper());
        mFileProvider = fileProvider;

        mPrintOptionsLayout = (PrintOptionsLayout) activity.findViewById(R.id.options_container);
        mPageAdapter = new PageAdapter(activity, activity, this);

        final int columnCount = mActivity.getResources().getInteger(
                R.integer.preview_page_per_row_count);

        mLayoutManger = new StaggeredGridLayoutManager(columnCount, OrientationHelper.VERTICAL);

        mRecyclerView = (RecyclerView) activity.findViewById(R.id.preview_content);
        mRecyclerView.setLayoutManager(mLayoutManger);
        mRecyclerView.setAdapter(mPageAdapter);
        mPreloadController = new PreloadController(mRecyclerView);
        mRecyclerView.setOnScrollListener(mPreloadController);

        mContentView = (PrintContentView) activity.findViewById(R.id.options_content);
        mEmbeddedContentContainer = (EmbeddedContentContainer) activity.findViewById(
                R.id.embedded_content_container);
        mEmbeddedContentContainer.setOnSizeChangeListener(this);
    }

    @Override
    public void onSizeChanged(int width, int height) {
        mPageAdapter.onPreviewAreaSizeChanged();
    }

    public boolean isOptionsOpened() {
        return mContentView.isOptionsOpened();
    }

    public void closeOptions() {
        mContentView.closeOptions();
    }

    public void setUiShown(boolean shown) {
        if (shown) {
            mRecyclerView.setVisibility(View.VISIBLE);
        } else {
            mRecyclerView.setVisibility(View.GONE);
        }
    }

    public void onOrientationChanged() {
        // Adjust the print option column count.
        final int optionColumnCount = mActivity.getResources().getInteger(
                R.integer.print_option_column_count);
        mPrintOptionsLayout.setColumnCount(optionColumnCount);
        mPageAdapter.onOrientationChanged();
    }

    public int getFilePageCount() {
        return mPageAdapter.getFilePageCount();
    }

    public PageRange[] getSelectedPages() {
        return mPageAdapter.getSelectedPages();
    }

    public PageRange[] getRequestedPages() {
        return mPageAdapter.getRequestedPages();
    }

    public void onContentUpdated(boolean documentChanged, int documentPageCount,
            PageRange[] writtenPages, PageRange[] selectedPages, MediaSize mediaSize,
            Margins minMargins) {
                boolean contentChanged = false;

        if (documentChanged) {
            contentChanged = true;
        }

        if (documentPageCount != mDocumentPageCount) {
            mDocumentPageCount = documentPageCount;
            contentChanged = true;
        }

        if (contentChanged) {
            // If not closed, close as we start over.
            if (mPageAdapter.isOpened()) {
                Message operation = mHandler.obtainMessage(MyHandler.MSG_CLOSE);
                mHandler.enqueueOperation(operation);
            }
        }

        // The content changed. In this case we have to invalidate
        // all rendered pages and reopen the file...
        if (contentChanged && writtenPages != null) {
            Message operation = mHandler.obtainMessage(MyHandler.MSG_OPEN);
            mHandler.enqueueOperation(operation);
        }

        // Update the attributes before after closed to avoid flicker.
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = writtenPages;
        args.arg2 = selectedPages;
        args.arg3 = mediaSize;
        args.arg4 = minMargins;
        args.argi1 = documentPageCount;

        Message operation = mHandler.obtainMessage(MyHandler.MSG_UPDATE, args);
        mHandler.enqueueOperation(operation);

        // If document changed and has pages we want to start preloading.
        if (contentChanged && writtenPages != null) {
            operation = mHandler.obtainMessage(MyHandler.MSG_START_PRELOAD);
            mHandler.enqueueOperation(operation);
        }
    }

    @Override
    public void onReleaseRequested(final File file) {
        // This is called from the async task's single threaded executor
        // thread, i.e. not on the main thread - so post a message.
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                // At this point the other end will write to the file, hence
                // we have to close it and reopen after the write completes.
                Message operation = mHandler.obtainMessage(MyHandler.MSG_CLOSE);
                mHandler.enqueueOperation(operation);
            }
        });
    }

    public void destroy() {
        mPageAdapter.destroy();
    }

    @Override
    public int getWidth() {
        return mEmbeddedContentContainer.getWidth();
    }

    @Override
    public int getHeight() {
        return mEmbeddedContentContainer.getHeight();
    }

    @Override
    public void setColumnCount(int columnCount) {
        mLayoutManger.setSpanCount(columnCount);
    }

    @Override
    public void setPadding(int left, int top , int right, int bottom) {
        mRecyclerView.setPadding(left, top, right, bottom);
    }

    private final class MyHandler extends Handler {
        public static final int MSG_OPEN = 1;
        public static final int MSG_CLOSE = 2;
        public static final int MSG_DESTROY = 3;
        public static final int MSG_UPDATE = 4;
        public static final int MSG_START_PRELOAD = 5;

        private boolean mAsyncOperationInProgress;

        private final Runnable mOnAsyncOperationDoneCallback = new Runnable() {
            @Override
            public void run() {
                mAsyncOperationInProgress = false;
                handleNextOperation();
            }
        };

        private final List<Message> mPendingOperations = new ArrayList<>();

        public MyHandler(Looper looper) {
            super(looper, null, false);
        }

        public void enqueueOperation(Message message) {
            mPendingOperations.add(message);
            handleNextOperation();
        }

        public void handleNextOperation() {
            while (!mPendingOperations.isEmpty() && !mAsyncOperationInProgress) {
                Message operation = mPendingOperations.remove(0);
                handleMessage(operation);
            }
        }

        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case MSG_OPEN: {
                    try {
                        File file = mFileProvider.acquireFile(PrintPreviewController.this);
                        ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file,
                                ParcelFileDescriptor.MODE_READ_ONLY);

                        mAsyncOperationInProgress = true;
                        mPageAdapter.open(pfd, new Runnable() {
                            @Override
                            public void run() {
                                if (mDocumentPageCount == PrintDocumentInfo.PAGE_COUNT_UNKNOWN) {
                                    mDocumentPageCount = mPageAdapter.getFilePageCount();
                                    mActivity.updateOptionsUi();
                                }
                                mOnAsyncOperationDoneCallback.run();
                            }
                        });
                    } catch (FileNotFoundException fnfe) {
                        /* ignore - file guaranteed to be there */
                    }
                } break;

                case MSG_CLOSE: {
                    mAsyncOperationInProgress = true;
                    mPageAdapter.close(new Runnable() {
                        @Override
                        public void run() {
                            mFileProvider.releaseFile();
                            mOnAsyncOperationDoneCallback.run();
                        }
                    });
                } break;

                case MSG_DESTROY: {
                    mPageAdapter.destroy();
                    handleNextOperation();
                } break;

                case MSG_UPDATE: {
                    SomeArgs args = (SomeArgs) message.obj;
                    PageRange[] writtenPages = (PageRange[]) args.arg1;
                    PageRange[] selectedPages = (PageRange[]) args.arg2;
                    MediaSize mediaSize = (MediaSize) args.arg3;
                    Margins margins = (Margins) args.arg4;
                    final int pageCount = args.argi1;
                    args.recycle();

                    mPageAdapter.update(writtenPages, selectedPages, pageCount,
                            mediaSize, margins);

                } break;

                case MSG_START_PRELOAD: {
                    mPreloadController.startPreloadContent();
                } break;
            }
        }
    }

    private final class PreloadController extends RecyclerView.OnScrollListener {
        private final RecyclerView mRecyclerView;

        private int mOldScrollState;

        public PreloadController(RecyclerView recyclerView) {
            mRecyclerView = recyclerView;
            mOldScrollState = mRecyclerView.getScrollState();
        }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int state) {
            switch (mOldScrollState) {
                case RecyclerView.SCROLL_STATE_SETTLING: {
                    if (state == RecyclerView.SCROLL_STATE_IDLE
                            || state == RecyclerView.SCROLL_STATE_DRAGGING){
                        startPreloadContent();
                    }
                } break;

                case RecyclerView.SCROLL_STATE_IDLE:
                case RecyclerView.SCROLL_STATE_DRAGGING: {
                    if (state == RecyclerView.SCROLL_STATE_SETTLING) {
                        stopPreloadContent();
                    }
                } break;
            }
            mOldScrollState = state;
        }

        public void startPreloadContent() {
            PageAdapter pageAdapter = (PageAdapter) mRecyclerView.getAdapter();

            if (pageAdapter.isOpened()) {
                PageRange shownPages = computeShownPages();
                if (shownPages != null) {
                    pageAdapter.startPreloadContent(shownPages);
                }
            }
        }

        public void stopPreloadContent() {
            PageAdapter pageAdapter = (PageAdapter) mRecyclerView.getAdapter();

            if (pageAdapter.isOpened()) {
                pageAdapter.stopPreloadContent();
            }
        }

        private PageRange computeShownPages() {
            final int childCount = mRecyclerView.getChildCount();
            if (childCount > 0) {
                LayoutManager layoutManager = mRecyclerView.getLayoutManager();

                View firstChild = layoutManager.getChildAt(0);
                ViewHolder firstHolder = mRecyclerView.getChildViewHolder(firstChild);

                View lastChild = layoutManager.getChildAt(layoutManager.getChildCount() - 1);
                ViewHolder lastHolder = mRecyclerView.getChildViewHolder(lastChild);

                return new PageRange(firstHolder.getPosition(), lastHolder.getPosition());
            }
            return null;
        }
    }
}
