package com.vise.facedemo;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.vise.face.CameraPreview;
import com.vise.face.DetectorData;
import com.vise.face.DetectorProxy;
import com.vise.face.FaceRectView;
import com.vise.face.ICameraCheckListener;
import com.vise.face.IDataListener;
import com.vise.log.ViseLog;
import com.vise.utils.assist.StringUtil;
import com.vise.utils.view.ViewUtil;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @Description: 拍照测肤界面
 * @author: <a href="http://xiaoyaoyou1212.360doc.com">DAWI</a>
 * @date: 2017/8/15 11:12
 */
public class FaceDetectorActivity extends Activity {

    private CameraPreview mFace_detector_preview;
    private FaceRectView mFace_detector_face;
    private Button mFace_detector_take_photo;
    private TextView mFace_detector_distance;

    private Context mContext;
    private DetectorProxy mDetectorProxy;
    private DetectorData mDetectorData;

    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (mDetectorData != null) {
                mFace_detector_distance.setText(StringUtil.parseStr(mDetectorData.getLightIntensity()));
            }
        }
    };

    private ICameraCheckListener mCameraCheckListener = new ICameraCheckListener() {
        @Override
        public void checkPermission(boolean isAllow) {
            ViseLog.i("checkPermission" + isAllow);
            if (!isAllow) {
                Toast.makeText(mContext, "权限申请被拒绝,请进入设置打开权限再试!", Toast.LENGTH_SHORT).show();
                finish();
            }
        }

        @Override
        public void checkPixels(long pixels, boolean isSupport) {
            ViseLog.i("checkPixels" + pixels);
            if (!isSupport) {
                Toast.makeText(mContext, "手机相机像素达不到要求!", Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    };

    private IDataListener mDataListener = new IDataListener() {
        @Override
        public void onDetectorData(DetectorData detectorData) {
            mDetectorData = detectorData;
            ViseLog.i("识别数据:" + detectorData);
            mHandler.sendEmptyMessage(0);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_face_detector);
        mContext = this;
        init();
    }

    protected void init() {
        mFace_detector_preview = (CameraPreview) findViewById(R.id.face_detector_preview);
        mFace_detector_face = (FaceRectView) findViewById(R.id.face_detector_face);
        mFace_detector_face.setZOrderOnTop(true);
        mFace_detector_face.getHolder().setFormat(PixelFormat.TRANSLUCENT);
        mFace_detector_take_photo = (Button) findViewById(R.id.face_detector_take_photo);
        mFace_detector_distance = (TextView) findViewById(R.id.face_detector_distance);

        // 点击SurfaceView,切换摄相头
        mFace_detector_preview.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // 只有一个摄相头,不支持切换
                if (Camera.getNumberOfCameras() == 1) {
                    return;
                }
                if (mDetectorProxy == null) {
                    return;
                }
                mDetectorProxy.closeCamera();
                if (Camera.CameraInfo.CAMERA_FACING_FRONT == mDetectorProxy.getCameraId()) {
                    mDetectorProxy.setCameraId(Camera.CameraInfo.CAMERA_FACING_BACK);
                } else {
                    mDetectorProxy.setCameraId(Camera.CameraInfo.CAMERA_FACING_FRONT);
                }
                mDetectorProxy.openCamera();
            }
        });

        mFace_detector_take_photo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mFace_detector_preview.getCamera().takePicture(new Camera.ShutterCallback() {
                    @Override
                    public void onShutter() {

                    }
                }, null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] bytes, Camera camera) {
                        mFace_detector_preview.getCamera().stopPreview();
                        saveImage(bytes);
                        finish();
                    }
                });
            }
        });

        mDetectorProxy = new DetectorProxy.Builder(mFace_detector_preview)
                .setMinCameraPixels(3000000)
                .setCheckListener(mCameraCheckListener)
                .setDataListener(mDataListener)
                .setFaceRectView(mFace_detector_face)
                .setDrawFaceRect(true)
                .build();
    }

    @Override
    protected void onStart() {
        super.onStart();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mDetectorProxy != null) {
            mDetectorProxy.detector();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mDetectorProxy != null) {
            mDetectorProxy.release();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.gc();
    }

    /**
     * 保存拍照的图片
     *
     * @param data
     */
    private void saveImage(byte[] data) {
        File pictureFile = getOutputFile(mContext, "face", "photo.jpg");//拍照图片
        File avatarFile = getOutputFile(mContext, "face", "avatar.jpg");//截取人脸图片
        if (pictureFile == null || avatarFile == null) {
            return;
        }
        if (pictureFile.exists()) {
            pictureFile.delete();
        }
        if (avatarFile.exists()) {
            avatarFile.delete();
        }
        Rect rect = new Rect();
        if (mDetectorData != null && mDetectorData.getFaceRectList() != null
                && mDetectorData.getFaceRectList().length > 0
                && mDetectorData.getFaceRectList()[0].right > 0) {
            rect = mDetectorData.getFaceRectList()[0];
        }
        ViseLog.i("save picture start!");
        Bitmap bitmap = getImage(data, rect, 1500, 2000, pictureFile, avatarFile);
        ViseLog.i("save picture complete!");
        if (bitmap != null) {
            bitmap.recycle();
            bitmap = null;
        }
    }

    private String getDiskCacheDir(Context context, String dirName) {
        String cachePath = "";
        if ((Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
                || !Environment.isExternalStorageRemovable())
                && context != null && context.getExternalCacheDir() != null) {
            cachePath = context.getExternalCacheDir().getPath();
        } else {
            if (context != null && context.getCacheDir() != null) {
                cachePath = context.getCacheDir().getPath();
            }
        }
        return cachePath + File.separator + dirName;
    }

    private File getOutputFile(Context context, String dirName, String fileName) {
        File dirFile = new File(getDiskCacheDir(context, dirName));
        if (!dirFile.exists()) {
            if (!dirFile.mkdirs()) {
                ViseLog.d("failed to create directory");
                return null;
            }
        }
        File file = new File(dirFile.getPath() + File.separator + fileName);
        return file;
    }

    private Bitmap getImage(byte[] data, Rect rect, float ww, float hh, File pictureFile, File avatarFile) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
        int w = options.outWidth;
        int h = options.outHeight;
        float scale = 1.0F;
        if (w < h) {
            scale = ww / (float) w;
            if (hh / (float) h > scale) {
                scale = hh / (float) h;
            }
        } else {
            scale = ww / (float) h;
            if (hh / (float) w > scale) {
                scale = hh / (float) w;
            }
        }

        Bitmap scaleBitmap = scaleImage(bitmap, (int) ((float) w * scale), (int) ((float) h * scale));
        if (bitmap != null && !bitmap.isRecycled()) {
            bitmap.recycle();
            bitmap = null;
        }

        return compressImage(scaleBitmap, rect, 1536, pictureFile, avatarFile);
    }

    private Bitmap compressImage(Bitmap image, Rect rect, int size, File pictureFile, File avatarFile) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Bitmap bitmap = image;
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        int options = 100;

        while (baos.toByteArray().length / 1024 > size) {
            baos.reset();
            options -= 5;
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
        }

        FileOutputStream fileOutputStream = null;

        try {
            fileOutputStream = new FileOutputStream(pictureFile);
            if (mFace_detector_preview != null) {
                if (mFace_detector_preview.getCameraId() == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    bitmap = rotaingImageView(360 - mFace_detector_preview.getDisplayOrientation(), bitmap);
                } else {
                    bitmap = rotaingImageView(mFace_detector_preview.getDisplayOrientation(), bitmap);
                }
            }
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, fileOutputStream);
        } catch (FileNotFoundException var18) {
            ViseLog.e("File not found: " + var18.getMessage());
        } finally {
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }
            } catch (IOException var16) {
                ViseLog.e("Error accessing file: " + var16.getMessage());
            }

        }

        float scale = (float) bitmap.getHeight() / ViewUtil.getScreenHeight(mContext);
        if (rect.right > 0) {
            int top = (int) (rect.top * scale);
            int bottom = (int) (rect.bottom * scale);
            rect.left = 0;
            rect.right = bitmap.getWidth();
            rect.top = top - (bitmap.getWidth() - (bottom - top)) / 2;
            rect.bottom = bottom + (bitmap.getWidth() - (bottom - top)) / 2;
        } else {
            rect.left = 0;
            rect.right = bitmap.getWidth();
            rect.top = (bitmap.getHeight() - bitmap.getWidth()) / 2;
            rect.bottom = (bitmap.getHeight() - bitmap.getWidth()) / 2 + bitmap.getWidth();
        }
        Bitmap avatarBitmap = Bitmap.createBitmap(bitmap, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
        try {
            fileOutputStream = new FileOutputStream(avatarFile);
            avatarBitmap.compress(Bitmap.CompressFormat.JPEG, 50, fileOutputStream);
        } catch (FileNotFoundException var18) {
            ViseLog.e("File not found: " + var18.getMessage());
        } finally {
            if (avatarBitmap != null && !avatarBitmap.isRecycled()) {
                avatarBitmap.recycle();
                avatarBitmap = null;
            }
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }
            } catch (IOException var16) {
                ViseLog.e("Error accessing file: " + var16.getMessage());
            }

        }

        if (baos != null) {
            try {
                baos.close();
            } catch (IOException var17) {
                var17.printStackTrace();
            }
        }

        if (image != null && !image.isRecycled()) {
            image.recycle();
            image = null;
        }

        return bitmap;
    }

    private Bitmap scaleImage(Bitmap bm, int newWidth, int newHeight) {
        if (bm == null) {
            return null;
        } else {
            int width = bm.getWidth();
            int height = bm.getHeight();
            float scaleWidth = (float) newWidth / (float) width;
            float scaleHeight = (float) newHeight / (float) height;
            Matrix matrix = new Matrix();
            matrix.postScale(scaleWidth, scaleHeight);
            Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
            if (bm != null & !bm.isRecycled()) {
                bm.recycle();
                bm = null;
            }

            return newbm;
        }
    }

    private Bitmap rotaingImageView(int angle, Bitmap bitmap) {
        Matrix matrix = new Matrix();
        matrix.postRotate((float) angle);
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        if (resizedBitmap != bitmap && bitmap != null && !bitmap.isRecycled()) {
            bitmap.recycle();
            bitmap = null;
        }

        return resizedBitmap;
    }

}