package com.base.utils.tools.android;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.LruCache;
import android.view.Display;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ScrollView;

import com.base.utils.Config;
import com.base.utils.R;
import com.base.utils.tools.java.DateUtil;
import com.base.utils.tools.java.FileUtil;
import com.base.utils.ui.dialog.DialogUtil;

import java.lang.reflect.Method;

/**
 * 截屏工具
 *
 * @author yuyife
 * @date 2018-06-06
 */

public class ScreenShotUtil {
    /**
     * 获取是否存在NavigationBar
     *
     * @param context
     * @return
     */
    public static boolean checkDeviceHasNavigationBar(Context context) {
        boolean hasNavigationBar = false;
        Resources rs = context.getResources();
        int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
        if (id > 0) {
            hasNavigationBar = rs.getBoolean(id);
        }
        try {
            Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
            Method m = systemPropertiesClass.getMethod("get", String.class);
            String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
            if ("1".equals(navBarOverride)) {
                hasNavigationBar = false;
            } else if ("0".equals(navBarOverride)) {
                hasNavigationBar = true;
            }
        } catch (Exception e) {

        }
        return hasNavigationBar;
    }



    /**
     * 根据手机分辨率从DP转成PX
     *
     * @param context
     * @param dpValue
     * @return
     */
    public static int dip2px(Context context, float dpValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


    /**
     * 根据手机的分辨率PX(像素)转成DP
     *
     * @param context
     * @param pxValue
     * @return
     */
    public static int px2dip(Context context, float pxValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    private static final int REQUEST_MEDIA_PROJECTION = 18;

    /**
     * 申请录屏权限,
     * 1.失败，会弹出提示
     * 2.成功，会调用 @param activity 的 onActivityResult(int requestCode, int resultCode, Intent data)
     * 3.在onActivityResult（） 调用 responseCapture（）
     **/
    @SuppressLint("NewApi")
    public static void requestCapture(Activity activity) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            //5.0 之后才允许使用屏幕截图
            //showTips(activity);
            LogUtil.err(ScreenShotUtil.class, "requestCapture nonsupport");
        } else {
            try {
                //申请录屏
                MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
                activity.startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
            } catch (Exception e) {
                //showTips(activity);
                LogUtil.err(ScreenShotUtil.class, "requestCapture nonsupport");
            }
        }
    }

    private static Dialog dialog;

    /**
     * 弹出提示
     **/
    private static void showTips(Context context) {
        dialog = DialogUtil.getDialog(context).setCancelable(false).setTitle(R.string.auto_screen_tips)
                .setMessage(R.string.auto_screen_content).setPositiveButton(R.string.resource_public_close, null).create();
        dialog.show();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                closeTips();
            }
        }, 3 * 1000);
    }

    private static void closeTips() {
        if (dialog != null) {
            dialog.dismiss();
        }
    }

    /**
     * 响应录屏捕获
     *
     * @return Intent mResultData 用于getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
     */
    public static Intent responseCapture(int requestCode, int resultCode, Intent mResultData) {
        switch (requestCode) {
            case REQUEST_MEDIA_PROJECTION:
                if (resultCode == Activity.RESULT_OK && mResultData != null) {
                    ScreenShotUtil.mResultData = mResultData;
                    return ScreenShotUtil.mResultData;
                }
                break;
        }
        return null;
    }

    private static Intent mResultData = null;


    private Activity mActivity;
    private WindowManager mWindowManager;                 //window

    private ScreenShotUtil(Activity activity) {
        this.mActivity = activity;
        mWindowManager = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics = new DisplayMetrics();
        mWindowManager.getDefaultDisplay().getMetrics(metrics);
        mScreenDensity = metrics.densityDpi;
        mScreenWidth = metrics.widthPixels;
        mScreenHeight = metrics.heightPixels;

        createImageReader();
    }

    private static ScreenShotUtil mInstance;

    public synchronized static ScreenShotUtil getInstance(Activity activity) {
        synchronized (ScreenShotUtil.class) {
            if (mInstance == null) {
                mInstance = new ScreenShotUtil(activity);
            }
            return mInstance;
        }
    }

    private MediaProjection mMediaProjection;             //录屏API
    private VirtualDisplay mVirtualDisplay;               //虚拟显示 VirtualDisplay类代表一个虚拟显示器，需要调用DisplayManager 类的 createVirtualDisplay()方法，将虚拟显示器的内容渲染在一个Surface控件上，当进程终止时虚拟显示器会被自动的释放，并且所有的Window都会被强制移除。当不再使用他时，你应该调用release() 方法来释放资源。
    private ImageReader mImageReader;                     //图片读取


    private static Handler handler = new Handler(Looper.getMainLooper());

    /**
     * 开始截图,外部应调用这个方法。
     */
    public void startScreenShot(final OnCaptureListener listener) {
        if (handler == null) {
            handler = new Handler(Looper.getMainLooper());
        }
        handler.postDelayed(new Runnable() {
            public void run() {
                startVirtual();
            }
        }, 15);

        handler.postDelayed(new Runnable() {
            public void run() {
                try {
                    startCapture(listener);
                } catch (Exception e) {
                    e.printStackTrace();
                    captureFlag = 0;
                    if (listener != null) {
                        listener.done(null);
                    }
                }
            }
        }, 45);
    }

    private int mScreenWidth;                            //屏幕宽
    private int mScreenHeight;                           //屏幕高
    private int mScreenDensity;                          //屏幕密度

    /**
     * 创建图片读取的对象
     */
    @SuppressLint("NewApi")
    private void createImageReader() {
        mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1);
    }

    /**
     * 开始虚拟
     */
    private void startVirtual() {
        if (mMediaProjection != null) {
            virtualDisplay();
        } else {
            setUpMediaProjection();
            virtualDisplay();
        }
    }

    @SuppressLint("NewApi")
    private void setUpMediaProjection() {
        if (mResultData != null) {
            mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
        }
    }

    @SuppressLint("NewApi")
    private MediaProjectionManager getMediaProjectionManager() {
        return (MediaProjectionManager) mActivity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    }

    @SuppressLint("NewApi")
    private void virtualDisplay() {
        mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
                mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mImageReader.getSurface(), new VirtualDisplay.Callback() {
                    @Override
                    public void onPaused() {
                        super.onPaused();
                        Log.e(ScreenShotUtil.class.getSimpleName(), "onPaused:");
                    }

                    @Override
                    public void onResumed() {
                        super.onResumed();
                        Log.e(ScreenShotUtil.class.getSimpleName(), "onResumed:");
                    }

                    @Override
                    public void onStopped() {
                        super.onStopped();
                        Log.e(ScreenShotUtil.class.getSimpleName(), "onStopped:");
                    }
                }, handler);
    }

    private int captureFlag = 0;//循环30次如果还没有截图成功。就不截图了。

    /**
     * 开始截图
     */
    @SuppressLint("NewApi")
    private void startCapture(OnCaptureListener listener) {
        captureFlag += 1;
        Image image = mImageReader.acquireLatestImage();
        if (image != null) {
            captureFlag = 0;
            //保存
            String imageName = Config.appPrimary + DateUtil.getTodayYYYYMMDDHHMMSS();
            Bitmap bitmap = FileUtil.imageTransformBitmap(image, imageName);
            if (listener != null) {
                listener.done(bitmap);
            }

        } else {
            if (captureFlag >= 30) {
                captureFlag = 0;
                if (listener != null) {
                    listener.done(null);
                }
            } else {
                startScreenShot(listener);
            }
        }
    }

    public interface OnCaptureListener {
        void done(Bitmap bitmap);
    }

    @SuppressLint("NewApi")
    private void stopMediaProjection() {
        if (mMediaProjection != null) {
            mMediaProjection.stop();
            mMediaProjection = null;
        }
    }

    @SuppressLint("NewApi")
    private void stopVirtual() {
        if (mVirtualDisplay != null) {
            mVirtualDisplay.release();
            mVirtualDisplay = null;
        }
    }


    /**
     * 销毁
     */
    public void onDestroy() {
        stopVirtual();
        stopMediaProjection();
        mActivity = null;
        mInstance = null;
        handler = null;
    }


    /**
     * 截取某个Activity全屏
     *
     * @return Bitmap
     */
    public static Bitmap captureScreenWindow(Activity activity) {
        activity.getWindow().getDecorView().setDrawingCacheEnabled(true); //开启缓存
        return activity.getWindow().getDecorView().getDrawingCache();
    }

    /**
     * 截取某个View 的屏
     *
     * @return Bitmap
     */
    public static Bitmap captureViewWindow(View view) {
        view.setDrawingCacheEnabled(true);                   //开启缓存
        return view.getDrawingCache();
    }

    /**
     * 截取 ScrollView 的屏
     *
     * @return Bitmap
     */
    public static Bitmap captureScrollView(ScrollView scrollView) {
        int h = 0;
        Bitmap bitmap;
        for (int i = 0; i < scrollView.getChildCount(); i++) {
            h += scrollView.getChildAt(i).getHeight();
            scrollView.getChildAt(i).setBackgroundColor(Color.parseColor("#ffffff"));
        }
        bitmap = Bitmap.createBitmap(scrollView.getWidth(), h, Bitmap.Config.RGB_565);
        final Canvas canvas = new Canvas(bitmap);
        scrollView.draw(canvas);
        return bitmap;
    }

    /**
     * 截取 RecyclerView 的屏
     * https://gist.github.com/PrashamTrivedi/809d2541776c8c141d9a
     */
    public static Bitmap captureRecyclerView(RecyclerView view) {
        RecyclerView.Adapter adapter = view.getAdapter();
        Bitmap bigBitmap = null;
        if (adapter != null) {
            int size = adapter.getItemCount();
            int height = 0;
            Paint paint = new Paint();
            int iHeight = 0;
            final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

            // Use 1/8th of the available memory for this memory cache.
            final int cacheSize = maxMemory / 8;
            LruCache<String, Bitmap> bitmaCache = new LruCache<>(cacheSize);
            for (int i = 0; i < size; i++) {
                RecyclerView.ViewHolder holder = adapter.createViewHolder(view, adapter.getItemViewType(i));
                adapter.onBindViewHolder(holder, i);
                holder.itemView.measure(
                        View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(),
                        holder.itemView.getMeasuredHeight());
                holder.itemView.setDrawingCacheEnabled(true);
                holder.itemView.buildDrawingCache();
                Bitmap drawingCache = holder.itemView.getDrawingCache();
                if (drawingCache != null) {

                    bitmaCache.put(String.valueOf(i), drawingCache);
                }
                height += holder.itemView.getMeasuredHeight();
            }

            bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height, Bitmap.Config.ARGB_8888);
            Canvas bigCanvas = new Canvas(bigBitmap);
            Drawable lBackground = view.getBackground();
            if (lBackground instanceof ColorDrawable) {
                ColorDrawable lColorDrawable = (ColorDrawable) lBackground;
                int lColor = lColorDrawable.getColor();
                bigCanvas.drawColor(lColor);
            }

            for (int i = 0; i < size; i++) {
                Bitmap bitmap = bitmaCache.get(String.valueOf(i));
                bigCanvas.drawBitmap(bitmap, 0f, iHeight, paint);
                iHeight += bitmap.getHeight();
                bitmap.recycle();
            }
        }
        return bigBitmap;
    }

    private static WindowManager getWindowManager(Context context) {
        return (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    }

    /**
     * 获得屏幕宽度
     *
     * @param context
     * @return
     */
    public static int getScreenWidth(Context context) {
        DisplayMetrics outMetrics = new DisplayMetrics();
        getWindowManager(context).getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.widthPixels;
    }

    /**
     * 获得屏幕高度
     *
     * @param context
     * @return
     */
    public static int getScreenHeight(Context context) {
        DisplayMetrics outMetrics = new DisplayMetrics();
        getWindowManager(context).getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.heightPixels;
    }

    /**
     * 获得屏幕密度Dpi
     *
     * @param context
     * @return
     */
    public static int getScreenDensityDpi(Context context) {
        DisplayMetrics outMetrics = new DisplayMetrics();
        getWindowManager(context).getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.densityDpi;
    }

    /**
     * get the height of title *
     */
    public static int getTitleH(Activity ctx) {
        int contentTop = ctx.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
        return contentTop - getStatusH(ctx);
    }

    /**
     * get the height of status *
     */
    public static int getStatusH(Context ctx) {
        int statusHeight = -1;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            int height = Integer.parseInt(clazz.getField("status_bar_height")
                    .get(object).toString());
            statusHeight = ctx.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusHeight;
    }

    /**
     * get the height of status *
     */
    public static int getStatusH(Activity ctx) {
        Rect s = new Rect();
        ctx.getWindow().getDecorView().getWindowVisibleDisplayFrame(s);
        return s.top;
    }

    /**
     * get the width of screen **
     */
    public static int getScreenW(Context ctx) {
        int w = 0;
        if (Build.VERSION.SDK_INT > 13) {
            Point p = new Point();
            getWindowManager(ctx).getDefaultDisplay().getSize(p);
            w = p.x;
        } else {
            w = getWindowManager(ctx).getDefaultDisplay().getWidth();
        }
        return w;
    }

    /**
     * get the height of screen *
     */
    public static int getScreenH(Context ctx) {
        int h = 0;
        if (Build.VERSION.SDK_INT > 13) {
            Point p = new Point();
            getWindowManager(ctx).getDefaultDisplay().getSize(p);
            h = p.y;
        } else {
            h = getWindowManager(ctx).getDefaultDisplay().getHeight();
        }
        return h;
    }
}
