/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.gecko;

import android.annotation.TargetApi;
import android.app.Presentation;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.media.MediaRouter;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.view.WindowManager;

import org.mozilla.gecko.AppConstants.Versions;

import org.mozilla.gecko.annotation.WrapForJNI;

/**
 * A MediaPlayerManager with API 17+ Presentation support.
 */
@TargetApi(17)
public class PresentationMediaPlayerManager extends MediaPlayerManager {

    private static final String LOGTAG = "Gecko" + PresentationMediaPlayerManager.class.getSimpleName();

    private GeckoPresentation presentation;

    public PresentationMediaPlayerManager() {
        if (!Versions.feature17Plus) {
            throw new IllegalStateException(PresentationMediaPlayerManager.class.getSimpleName() +
                    " does not support < API 17");
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (presentation != null) {
            presentation.dismiss();
            presentation = null;
        }
    }

    @Override
    protected void updatePresentation() {
        if (mediaRouter == null) {
            return;
        }

        if (isPresentationMode) {
            return;
        }

        MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute();
        Display display = route != null ? route.getPresentationDisplay() : null;

        if (display != null) {
            if ((presentation != null) && (presentation.getDisplay() != display)) {
                presentation.dismiss();
                presentation = null;
            }

            if (presentation == null) {
                final GeckoView geckoView = (GeckoView) getActivity().findViewById(R.id.layer_view);
                presentation = new GeckoPresentation(getActivity(), display, geckoView);

                try {
                    presentation.show();
                } catch (WindowManager.InvalidDisplayException ex) {
                    Log.w(LOGTAG, "Couldn't show presentation!  Display was removed in "
                            + "the meantime.", ex);
                    presentation = null;
                }
            }
        } else if (presentation != null) {
            presentation.dismiss();
            presentation = null;
        }
    }

    @WrapForJNI(calledFrom = "ui")
    /* protected */ static native void invalidateAndScheduleComposite(GeckoView geckoView);

    @WrapForJNI(calledFrom = "ui")
    /* protected */ static native void addPresentationSurface(GeckoView geckoView, Surface surface);

    @WrapForJNI(calledFrom = "ui")
    /* protected */ static native void removePresentationSurface();

    private static final class GeckoPresentation extends Presentation {
        private SurfaceView mView;
        private GeckoView mGeckoView;

        public GeckoPresentation(Context context, Display display, GeckoView geckoView) {
            super(context, display);

            mGeckoView = geckoView;
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            mView = new SurfaceView(getContext());
            setContentView(mView, new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT));
            mView.getHolder().addCallback(new SurfaceListener(mGeckoView));
        }
    }

    private static final class SurfaceListener implements SurfaceHolder.Callback {
        private GeckoView mGeckoView;

        public SurfaceListener(GeckoView geckoView) {
            mGeckoView = geckoView;
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                   int height) {
            // Surface changed so force a composite
            if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
                invalidateAndScheduleComposite(mGeckoView);
            }
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
                addPresentationSurface(mGeckoView, holder.getSurface());
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
                removePresentationSurface();
            }
        }
    }
}
