//================================================================================================================================
//
// Copyright (c) 2015-2022 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================

package cn.easyar.samples.helloarrecording;

import android.Manifest;
import android.annotation.TargetApi;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;

import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.util.Log;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

import cn.easyar.CameraDevice;
import cn.easyar.FunctorOfVoidFromPermissionStatusAndString;
import cn.easyar.FunctorOfVoidFromRecordStatusAndString;
import cn.easyar.PermissionStatus;
import cn.easyar.RecordStatus;
import cn.easyar.Engine;
import cn.easyar.Recorder;

import android.app.Activity;

public class ARActivity extends Activity
{
    /*
    * Steps to create the key for this sample:
    *  1. login www.easyar.com
    *  2. create app with
    *      Name: HelloARRecording
    *      Package Name: cn.easyar.samples.helloarrecording
    *  3. find the created item in the list and show key
    *  4. set key string bellow
    */
    private static String key = "===PLEASE ENTER YOUR KEY HERE===";
    private GLView glView;
    private String url = "";
    private boolean started = false;

    private String prepareUrl()
    {
        String timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date());
        String FileName = "EasyAR_Recording_" + timeStamp + ".mp4";
        File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
        if (Build.VERSION.SDK_INT <= 28) {
            if (!folder.exists()) {
                folder.mkdirs();
            }
        }
        return (new File(folder, FileName)).getPath();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ar);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        if (!Engine.initialize(this, key)) {
            Log.e("HelloAR", "Initialization Failed.");
            Toast.makeText(ARActivity.this, Engine.errorMessage(), Toast.LENGTH_LONG).show();
            return;
        }

        if (!CameraDevice.isAvailable()) {
            Toast.makeText(ARActivity.this, "CameraDevice not available.", Toast.LENGTH_LONG).show();
            return;
        }
        if (!Recorder.isAvailable()) {
            Toast.makeText(ARActivity.this, "Recorder not available.", Toast.LENGTH_LONG).show();
            return;
        }

        glView = new GLView(this);

        requestPermissions(new String[] { Manifest.permission.CAMERA }, new PermissionCallback() {
            @Override
            public void onSuccess() {
                ((ViewGroup) findViewById(R.id.preview)).addView(glView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

                final Button recordCapture  = (Button)findViewById(R.id.ib_capture );
                recordCapture.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (started) {
                            started = false;
                            recordCapture.setText("CAPTURE");
                            glView.stopRecording();
                            Toast.makeText(ARActivity.this, "Recorded at " + url, Toast.LENGTH_LONG).show();
                            return;
                        }
                        requestPermissions(Build.VERSION.SDK_INT >= 30 ? new String[] { Manifest.permission.RECORD_AUDIO } : new String[] { Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE }, new PermissionCallback() {
                            @Override
                            public void onSuccess() {
                                glView.requestPermissions(new FunctorOfVoidFromPermissionStatusAndString() {
                                    @Override
                                    public void invoke(int status, String msg) {
                                        switch (status)
                                        {
                                            case PermissionStatus.Denied:
                                                started = false;
                                                recordCapture.setText("CAPTURE");
                                                Log.e("HelloAR", "Permission Denied" + msg);
                                                Toast.makeText(ARActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
                                                break;
                                            case PermissionStatus.Error:
                                                started = false;
                                                recordCapture.setText("CAPTURE");
                                                Log.e("HelloAR", "Permission Error" + msg);
                                                Toast.makeText(ARActivity.this, "Permission Error", Toast.LENGTH_SHORT).show();
                                                break;
                                            case PermissionStatus.Granted:
                                                Log.i("HelloAR", "Permission Granted");

                                                url = prepareUrl();

                                                glView.startRecording(url, new FunctorOfVoidFromRecordStatusAndString() {
                                                    @Override
                                                    public void invoke(int status, String value) {
                                                        switch (status)
                                                        {
                                                            case RecordStatus.OnStarted:
                                                                break;
                                                            case RecordStatus.OnStopped:
                                                                started = false;
                                                                recordCapture.setText("CAPTURE");
                                                                break;
                                                            case RecordStatus.FileFailed:
                                                                started = false;
                                                                recordCapture.setText("CAPTURE");
                                                                break;
                                                            case RecordStatus.FailedToStart:
                                                                started = false;
                                                                recordCapture.setText("CAPTURE");
                                                                Toast.makeText(ARActivity.this, value, Toast.LENGTH_LONG).show();
                                                                break;
                                                            default:
                                                                break;

                                                        }
                                                        Log.i("HelloAR", "Recorder Callback status: " + Integer.toString(status) + ", MSG: " + value);
                                                    }
                                                });
                                                Toast.makeText(ARActivity.this, "Recording...", Toast.LENGTH_SHORT).show();
                                                break;
                                        }
                                    }
                                });
                            }
                            @Override
                            public void onFailure() {
                                started = false;
                                recordCapture.setText("CAPTURE");
                                Log.e("HelloAR", "Permission Denied");
                                Toast.makeText(ARActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
                            }
                        });
                        started = true;
                        recordCapture.setText("STOP");
                    }
                });
            }

            @Override
            public void onFailure() {
            }
        });
    }

    private interface PermissionCallback
    {
        void onSuccess();
        void onFailure();
    }
    private HashMap<Integer, PermissionCallback> permissionCallbacks = new HashMap<Integer, PermissionCallback>();
    private int permissionRequestCodeSerial = 0;
    @TargetApi(23)
    private void requestPermissions(String[] permissions, PermissionCallback callback)
    {
        if (Build.VERSION.SDK_INT >= 23) {
            boolean allGranted = true;
            for (String p : permissions) {
                if (checkSelfPermission(p) != PackageManager.PERMISSION_GRANTED) {
                    allGranted = false;
                    break;
                }
            }
            if (!allGranted) {
                int requestCode = permissionRequestCodeSerial;
                permissionRequestCodeSerial += 1;
                permissionCallbacks.put(requestCode, callback);
                requestPermissions(permissions, requestCode);
            } else {
                callback.onSuccess();
            }
        } else {
            callback.onSuccess();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
    {
        if (permissionCallbacks.containsKey(requestCode)) {
            PermissionCallback callback = permissionCallbacks.get(requestCode);
            permissionCallbacks.remove(requestCode);
            boolean executed = false;
            for (int result : grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    executed = true;
                    callback.onFailure();
                }
            }
            if (!executed) {
                callback.onSuccess();
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        if (!started) {
            return;
        }
        started = false;
        glView.stopRecording();
        Toast.makeText(ARActivity.this, "Recorded at " + url, Toast.LENGTH_LONG).show();
    }

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

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