/*
 * Copyright (C) 2012 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.server.display;

import com.android.internal.util.DumpUtils;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.display.DisplayManager;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.TextureView;
import android.view.View;
import android.view.WindowManager;
import android.view.TextureView.SurfaceTextureListener;
import android.widget.TextView;

import java.io.PrintWriter;

/**
 * Manages an overlay window on behalf of {@link OverlayDisplayAdapter}.
 * <p>
 * This object must only be accessed on the UI thread.
 * No locks are held by this object and locks must not be held while making called into it.
 * </p>
 */
final class OverlayDisplayWindow implements DumpUtils.Dump {
    private static final String TAG = "OverlayDisplayWindow";
    private static final boolean DEBUG = false;

    private final float INITIAL_SCALE = 0.5f;
    private final float MIN_SCALE = 0.3f;
    private final float MAX_SCALE = 1.0f;
    private final float WINDOW_ALPHA = 0.8f;

    // When true, disables support for moving and resizing the overlay.
    // The window is made non-touchable, which makes it possible to
    // directly interact with the content underneath.
    private final boolean DISABLE_MOVE_AND_RESIZE = false;

    private final Context mContext;
    private final String mName;
    private final int mWidth;
    private final int mHeight;
    private final int mDensityDpi;
    private final int mGravity;
    private final boolean mSecure;
    private final Listener mListener;
    private String mTitle;

    private final DisplayManager mDisplayManager;
    private final WindowManager mWindowManager;


    private final Display mDefaultDisplay;
    private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();

    private View mWindowContent;
    private WindowManager.LayoutParams mWindowParams;
    private TextureView mTextureView;
    private TextView mTitleTextView;

    private GestureDetector mGestureDetector;
    private ScaleGestureDetector mScaleGestureDetector;

    private boolean mWindowVisible;
    private int mWindowX;
    private int mWindowY;
    private float mWindowScale;

    private float mLiveTranslationX;
    private float mLiveTranslationY;
    private float mLiveScale = 1.0f;

    public OverlayDisplayWindow(Context context, String name,
            int width, int height, int densityDpi, int gravity, boolean secure,
            Listener listener) {
        mContext = context;
        mName = name;
        mWidth = width;
        mHeight = height;
        mDensityDpi = densityDpi;
        mGravity = gravity;
        mSecure = secure;
        mListener = listener;
        mTitle = context.getResources().getString(
                com.android.internal.R.string.display_manager_overlay_display_title,
                mName, mWidth, mHeight, mDensityDpi);
        if (secure) {
            mTitle += context.getResources().getString(
                    com.android.internal.R.string.display_manager_overlay_display_secure_suffix);
        }

        mDisplayManager = (DisplayManager)context.getSystemService(
                Context.DISPLAY_SERVICE);
        mWindowManager = (WindowManager)context.getSystemService(
                Context.WINDOW_SERVICE);

        mDefaultDisplay = mWindowManager.getDefaultDisplay();
        updateDefaultDisplayInfo();

        createWindow();
    }

    public void show() {
        if (!mWindowVisible) {
            mDisplayManager.registerDisplayListener(mDisplayListener, null);
            if (!updateDefaultDisplayInfo()) {
                mDisplayManager.unregisterDisplayListener(mDisplayListener);
                return;
            }

            clearLiveState();
            updateWindowParams();
            mWindowManager.addView(mWindowContent, mWindowParams);
            mWindowVisible = true;
        }
    }

    public void dismiss() {
        if (mWindowVisible) {
            mDisplayManager.unregisterDisplayListener(mDisplayListener);
            mWindowManager.removeView(mWindowContent);
            mWindowVisible = false;
        }
    }

    public void relayout() {
        if (mWindowVisible) {
            updateWindowParams();
            mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
        }
    }

    @Override
    public void dump(PrintWriter pw) {
        pw.println("mWindowVisible=" + mWindowVisible);
        pw.println("mWindowX=" + mWindowX);
        pw.println("mWindowY=" + mWindowY);
        pw.println("mWindowScale=" + mWindowScale);
        pw.println("mWindowParams=" + mWindowParams);
        if (mTextureView != null) {
            pw.println("mTextureView.getScaleX()=" + mTextureView.getScaleX());
            pw.println("mTextureView.getScaleY()=" + mTextureView.getScaleY());
        }
        pw.println("mLiveTranslationX=" + mLiveTranslationX);
        pw.println("mLiveTranslationY=" + mLiveTranslationY);
        pw.println("mLiveScale=" + mLiveScale);
    }

    private boolean updateDefaultDisplayInfo() {
        if (!mDefaultDisplay.getDisplayInfo(mDefaultDisplayInfo)) {
            Slog.w(TAG, "Cannot show overlay display because there is no "
                    + "default display upon which to show it.");
            return false;
        }
        return true;
    }

    private void createWindow() {
        LayoutInflater inflater = LayoutInflater.from(mContext);

        mWindowContent = inflater.inflate(
                com.android.internal.R.layout.overlay_display_window, null);
        mWindowContent.setOnTouchListener(mOnTouchListener);

        mTextureView = (TextureView)mWindowContent.findViewById(
                com.android.internal.R.id.overlay_display_window_texture);
        mTextureView.setPivotX(0);
        mTextureView.setPivotY(0);
        mTextureView.getLayoutParams().width = mWidth;
        mTextureView.getLayoutParams().height = mHeight;
        mTextureView.setOpaque(false);
        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);

        mTitleTextView = (TextView)mWindowContent.findViewById(
                com.android.internal.R.id.overlay_display_window_title);
        mTitleTextView.setText(mTitle);

        mWindowParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY);
        mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
        if (mSecure) {
            mWindowParams.flags |= WindowManager.LayoutParams.FLAG_SECURE;
        }
        if (DISABLE_MOVE_AND_RESIZE) {
            mWindowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        }
        mWindowParams.privateFlags |=
                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
        mWindowParams.alpha = WINDOW_ALPHA;
        mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
        mWindowParams.setTitle(mTitle);

        mGestureDetector = new GestureDetector(mContext, mOnGestureListener);
        mScaleGestureDetector = new ScaleGestureDetector(mContext, mOnScaleGestureListener);

        // Set the initial position and scale.
        // The position and scale will be clamped when the display is first shown.
        mWindowX = (mGravity & Gravity.LEFT) == Gravity.LEFT ?
                0 : mDefaultDisplayInfo.logicalWidth;
        mWindowY = (mGravity & Gravity.TOP) == Gravity.TOP ?
                0 : mDefaultDisplayInfo.logicalHeight;
        mWindowScale = INITIAL_SCALE;
    }

    private void updateWindowParams() {
        float scale = mWindowScale * mLiveScale;
        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalWidth / mWidth);
        scale = Math.min(scale, (float)mDefaultDisplayInfo.logicalHeight / mHeight);
        scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));

        float offsetScale = (scale / mWindowScale - 1.0f) * 0.5f;
        int width = (int)(mWidth * scale);
        int height = (int)(mHeight * scale);
        int x = (int)(mWindowX + mLiveTranslationX - width * offsetScale);
        int y = (int)(mWindowY + mLiveTranslationY - height * offsetScale);
        x = Math.max(0, Math.min(x, mDefaultDisplayInfo.logicalWidth - width));
        y = Math.max(0, Math.min(y, mDefaultDisplayInfo.logicalHeight - height));

        if (DEBUG) {
            Slog.d(TAG, "updateWindowParams: scale=" + scale
                    + ", offsetScale=" + offsetScale
                    + ", x=" + x + ", y=" + y
                    + ", width=" + width + ", height=" + height);
        }

        mTextureView.setScaleX(scale);
        mTextureView.setScaleY(scale);

        mWindowParams.x = x;
        mWindowParams.y = y;
        mWindowParams.width = width;
        mWindowParams.height = height;
    }

    private void saveWindowParams() {
        mWindowX = mWindowParams.x;
        mWindowY = mWindowParams.y;
        mWindowScale = mTextureView.getScaleX();
        clearLiveState();
    }

    private void clearLiveState() {
        mLiveTranslationX = 0f;
        mLiveTranslationY = 0f;
        mLiveScale = 1.0f;
    }

    private final DisplayManager.DisplayListener mDisplayListener =
            new DisplayManager.DisplayListener() {
        @Override
        public void onDisplayAdded(int displayId) {
        }

        @Override
        public void onDisplayChanged(int displayId) {
            if (displayId == mDefaultDisplay.getDisplayId()) {
                if (updateDefaultDisplayInfo()) {
                    relayout();
                } else {
                    dismiss();
                }
            }
        }

        @Override
        public void onDisplayRemoved(int displayId) {
            if (displayId == mDefaultDisplay.getDisplayId()) {
                dismiss();
            }
        }
    };

    private final SurfaceTextureListener mSurfaceTextureListener =
            new SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
                int width, int height) {
            mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate);
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
            mListener.onWindowDestroyed();
            return true;
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
                int width, int height) {
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
        }
    };

    private final View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            // Work in screen coordinates.
            final float oldX = event.getX();
            final float oldY = event.getY();
            event.setLocation(event.getRawX(), event.getRawY());

            mGestureDetector.onTouchEvent(event);
            mScaleGestureDetector.onTouchEvent(event);

            switch (event.getActionMasked()) {
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    saveWindowParams();
                    break;
            }

            // Revert to window coordinates.
            event.setLocation(oldX, oldY);
            return true;
        }
    };

    private final GestureDetector.OnGestureListener mOnGestureListener =
            new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
            mLiveTranslationX -= distanceX;
            mLiveTranslationY -= distanceY;
            relayout();
            return true;
        }
    };

    private final ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener =
            new ScaleGestureDetector.SimpleOnScaleGestureListener() {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            mLiveScale *= detector.getScaleFactor();
            relayout();
            return true;
        }
    };

    /**
     * Watches for significant changes in the overlay display window lifecycle.
     */
    public interface Listener {
        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate);
        public void onWindowDestroyed();
    }
}