package com.ck.camera.demo;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;


import CameraVision.CKSDK;

public class MainActivity extends AppCompatActivity implements CameraCallback, SurfaceHolder.Callback{

    // 相机状态
    enum CamState { OPENED, OPENING, CLOSED };

    private TextView m_textView;
    private TextView m_textDeviceNum;
    private SurfaceHolder m_PreviewHolder;

    // camera
    private Camera m_cam = new Camera(this);
    private CamState m_CamState = CamState.CLOSED;
    private Thread m_OpenThread;
    private Thread m_CapThread;
    private boolean m_QuitCapThread;
    private Timer m_timer;

    // control
    private boolean m_bSnap;
    private int m_SnapIndex;
    private boolean m_bRecord = false;

    // stat
    private long m_lastTime = 0;
    private int m_Disp = 0;
    private int m_lastDisp = 0;
    private int m_lastCap = 0;
    private int m_lastWidth = 0;
    private int m_lastHeight = 0;

    private Handler m_CapHandler = new Handler(){
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case 1:
                    if (m_cam.CameraIsOpen()) {
                        m_lastTime = 0;
                        m_Disp = 0;
                        m_lastDisp = 0;
                        m_lastCap = 0;
                        m_lastWidth = 0;
                        m_lastHeight = 0;

                        m_QuitCapThread = false;
                        m_CapThread = new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        while (!m_QuitCapThread) {
                                            if (m_bSnap) {
                                                Bitmap bmp = m_cam.CameraCaptureImage();
                                                if (bmp != null) {
                                                    SaveBitmap(bmp, String.format("cam_snap%03d.png", ++m_SnapIndex) );
                                                    m_bSnap = false;
                                                }
                                            }
                                            else {
                                                int result = m_cam.CameraCapture(m_CapHandler);
                                                /*if (result[0] == 0) {
                                                    m_lastWidth = result[1];
                                                    m_lastHeight = result[2];
                                                    ++m_Disp;
                                                }*/
                                            }
                                        }
                            }
                        });
                        m_CapThread.start();

                        TimerTask task = new TimerTask() {
                            public void run() {
                                Message message = new Message();
                                message.what = 2;
                                m_CapHandler.sendMessage(message);
                            }
                        };
                        m_timer = new Timer();
                        m_timer.schedule(task, 1000, 1000);

                        m_CamState = CamState.OPENED;
                        m_textView.setText("Camera open succeed");
                    } else {
                        m_CamState = CamState.CLOSED;
                        m_textView.setText("Camera init failed");
                    }
                    break;

                case 2:
                    CKSDK.tFrameStatistic.ByReference frameStatistic = new CKSDK.tFrameStatistic.ByReference();
                    int status = m_cam.CameraGetFrameStatistic(frameStatistic);
                    if(status != CKSDK.CameraSdkStatus.CAMERA_STATUS_SUCCESS.value)
                        break;
                    long curTime = System.currentTimeMillis();
                    if (m_lastTime > 0)
                    {
                        float DispFps = (float)(m_Disp - m_lastDisp) * 1000.0f / (float)(curTime - m_lastTime);
                        float CapFps = (float)(frameStatistic.iCapture - m_lastCap) * 1000.0f / (float)(curTime - m_lastTime);
                        m_textView.setText(String.format("size:%d*%d Disp:%.2f Cap:%.2f\nC:%d L:%d E:%d",
                                m_lastWidth, m_lastHeight, DispFps, CapFps, frameStatistic.iCapture, frameStatistic.iLost,
                                frameStatistic.iTotal - (frameStatistic.iCapture + frameStatistic.iLost)));
                    }
                    Log.i("CCamera", "cap:" + m_lastCap + "," + frameStatistic.iCapture + " disp:" + m_lastDisp + "," + m_Disp);
                    m_lastDisp = m_Disp;
                    m_lastCap = frameStatistic.iCapture;
                    m_lastTime = curTime;
                    break;
                case 3:
                    int iWidth, iHeight;
                    iWidth = msg.arg1;
                    iHeight = msg.arg2;
                    Bitmap frameBitmap = Bitmap.createBitmap((int[])msg.obj,
                            iWidth, iHeight, Bitmap.Config.ARGB_8888);

                    Matrix m = new Matrix();
                    m.setRotate(90, (float)iWidth/2, (float)iHeight/2);
                    Bitmap rotationBitmap = Bitmap.createBitmap(frameBitmap, 0, 0, iWidth, iHeight, m, true);

                    Rect src = new Rect(0, 0, rotationBitmap.getWidth(), rotationBitmap.getHeight());
                    Canvas canvas = m_PreviewHolder.lockCanvas();
                    Rect dest = new Rect(0, 0, canvas.getWidth(), canvas.getHeight());
                    //canvas.drawBitmap(rotationBitmap, 0, 0, null);
                    canvas.drawBitmap(rotationBitmap, src, dest, null);
                    m_PreviewHolder.unlockCanvasAndPost(canvas);
                    m_lastWidth = iWidth;
                    m_lastHeight = iHeight;
                    m_Disp++;
                    break;
            }

            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SurfaceView Preview = (SurfaceView)findViewById(R.id.Preview);
        m_PreviewHolder = Preview.getHolder();
        m_PreviewHolder.addCallback(this);

        // Example of a call to a native method
        m_textView = (TextView)findViewById(R.id.TV);
        m_textDeviceNum = (TextView)findViewById(R.id.NUM);

    }

    private boolean SaveBitmap(Bitmap bmp, String fileName) {
        File f = new File("/mnt/sdcard/", fileName);
        if (f.exists()) {
            f.delete();
        }

        Bitmap.CompressFormat format;
        if (fileName.endsWith("png"))
            format = Bitmap.CompressFormat.PNG;
        else
            format = Bitmap.CompressFormat.JPEG;

        try {
            FileOutputStream out = new FileOutputStream(f);
            bmp.compress(format, 80, out);
            out.flush();
            out.close();
            Log.i("TestJni", "save complete");
            return true;
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    }

    private void TerminateOpenThread() {
        if (m_OpenThread == null)
            return;
        if (m_OpenThread.isAlive()) {
            m_OpenThread.interrupt();
        }
        try {
            m_OpenThread.join(20);
        } catch (Exception e) {
        }
        m_OpenThread = null;
    }

    public void onEnumerateDeviceCompleted(int nDev) {
        if (nDev > 0) {
            TerminateOpenThread();

            m_textView.setText("Connect Camera ...");

            m_OpenThread = new Thread(new Runnable() {
                @Override
                public void run() {

                    int status = m_cam.CameraInitEx(0, -1, -1);
                    if(status == 0)
                    {
                        Log.i("MainActivity","CameraInitEx ok\n");
                    }else
                        Log.i("MainActivity","CameraInitEx err\n");;
                    Message message = new Message();
                    message.what = 1;
                    m_CapHandler.sendMessage(message);

                }
            });
            m_OpenThread.start();


            String strNum = nDev + "";

            m_textDeviceNum.setText(strNum);

        }
        else {
            m_CamState = CamState.CLOSED;
            m_textView.setText("Camera not found");
        }
    }



    protected  void openCamera()
            {
        if (m_PreviewHolder.getSurface() == null)
            return;

        if (m_CamState != CamState.CLOSED)
            return;

        m_CamState = CamState.OPENING;
        m_textView.setText("Enum Camera ...");

        m_cam.CameraEnumerateDeviceEx2(this);
    }

    protected  void closeCamera()
    {
        TerminateOpenThread();

        if (m_timer != null) {
            m_timer.cancel();
            m_timer = null;
        }

        if (m_CapThread != null) {
            m_QuitCapThread = true;
            try {
                m_CapThread.join();
            }catch (Exception e)
            {

            }
            m_CapThread = null;
        }

        m_cam.CameraUninit();

        m_CamState = CamState.CLOSED;
        m_textView.setText("Camera closed");
    }

    public void onClick_SetImageSize(View view){
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        if(imm != null) {
            imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
        }

        try {
            if (!m_cam.CameraIsOpen())
                return;
            m_cam.CameraSetImageResolution(CKSDK.emResolutionMode.IMAGEOUT_MODE_1280X960.value);
        }
        catch (Exception e) {
        }
    }

    public void onClick_WBOnce(View view){
        //if (!m_cam.CameraIsOpen())
        //    return;
        m_cam.CameraSetOnceWB();
    }

    public void onClick_Snap(View view){
        m_bSnap = true;
    }

    public void onClick_Record(View view){
        if(m_bRecord == false)
        {
            if(m_cam.CameraStartRecord()) {
                m_bRecord = true;
                Button recordButton = (Button)findViewById(R.id.buttonRecord);
                recordButton.setText("Stop record");
            }
        }
        else
        {
            if(m_cam.CameraStopRecord()) {
                m_bRecord = false;
                Button recordButton = (Button)findViewById(R.id.buttonRecord);
                recordButton.setText("Start record");
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.i("demo", "surfaceCreated");
        openCamera();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.i("demo", "surfaceChanged");
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.i("TestJni", "surfaceDestroyed");
        closeCamera();
    }
}
