package com.gingersoft.gsa.cloud.scan.mvp.ui.activity;

import android.Manifest;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import com.billy.cc.core.component.CC;
import com.billy.cc.core.component.CCResult;
import com.billy.cc.core.component.CCUtil;
import com.gingersoft.gsa.cloud.common.scan.ScanHelper;
import com.gingersoft.gsa.cloud.common.utils.view.BitmapUtil;
import com.gingersoft.gsa.cloud.scan.R;
import com.gingersoft.gsa.cloud.scan.R2;
import com.gingersoft.gsa.cloud.ui.widget.dialog.LoadingDialog;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.DecodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Reader;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.jess.arms.base.BaseActivity;
import com.jess.arms.di.component.AppComponent;
import com.jess.arms.mvp.BasePresenter;
import com.jess.arms.mvp.IView;
import com.jess.arms.utils.ArmsUtils;
import com.jess.arms.utils.Preconditions;
import com.qmuiteam.qmui.widget.QMUITopBar;
import com.xuexiang.rxutil2.rxjava.RxJavaUtils;
import com.xuexiang.rxutil2.rxjava.task.RxAsyncTask;

import java.util.Hashtable;

import butterknife.BindView;
import butterknife.OnClick;
import cn.bingoogolapple.qrcode.core.BarcodeType;
import cn.bingoogolapple.qrcode.core.QRCodeView;
import cn.bingoogolapple.qrcode.zxing.QRCodeDecoder;
import cn.bingoogolapple.qrcode.zxing.ZXingView;

public class MipcaCaptureActivity extends BaseActivity<BasePresenter> implements IView, QRCodeView.Delegate {


    @BindView(R2.id.topbar)
    QMUITopBar mTopBar;
    @BindView(R2.id.btn_album)
    TextView btn_album;

    @BindView(R2.id.zxingview)
    ZXingView mZXingView;

    private final int ALBUM_REQUEST_CODE = 6;
    public static final int PHOTOZOOM = 0; // 相册
    private String cameraPermissions = Manifest.permission.CAMERA;//请求的权限
    private String[] needPermissions = {
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
    };

    private String title = "掃碼";
    public final static String QR_RESULT_CODE = "qrCodeResult";

    public final static String SCAN_MODE = "scanMode";

    private BarcodeType navigateParam;

    @Override
    public void setupActivityComponent(@NonNull AppComponent appComponent) {
//        DaggerMipcaCaptureComponent //如找不到该类,请编译一下项目
//                .builder()
//                .appComponent(appComponent)
//                .view(this)
//                .build()
//                .inject(this);
    }

    @Override
    public int initView(@Nullable Bundle savedInstanceState) {
        return R.layout.base_activity_capture_new;
    }

    @Override
    public void initData(@Nullable Bundle savedInstanceState) {
        mZXingView.setDelegate(this);
        navigateParam = CCUtil.getNavigateParam(this, SCAN_MODE, BarcodeType.ALL);
        mZXingView.setType(navigateParam, null);
        if (BarcodeType.ONE_DIMENSION == navigateParam) {
            mZXingView.changeToScanBarcodeStyle();
        }
    }

    @Override
    public void initIntent() {
        Intent intent = getIntent();
        title = intent.getStringExtra("title");
    }

    @Override
    public void initTopBar() {
        mTopBar.setBackgroundColor(ContextCompat.getColor(this, R.color.theme_color));
        mTopBar.removeAllLeftViews();
        mTopBar.addLeftBackImageButton().setOnClickListener(v -> scanResult(""));
        mTopBar.setTitle(title);
    }

    @Override
    public void onBackPressed() {
        scanResult("");
    }

    @Override
    public void initLanguage() {

    }

    @Override
    public void initLayoutParams() {

    }

    @Override
    public void initLayoutVisible() {

    }

    @Override
    protected void onStart() {
        super.onStart();

        mZXingView.startCamera(); // 打开后置摄像头开始预览，但是并未开始识别
//        mZXingView.startCamera(Camera.CameraInfo.CAMERA_FACING_FRONT); // 打开前置摄像头开始预览，但是并未开始识别

        mZXingView.startSpotAndShowRect(); // 显示扫描框，并开始识别
    }

    @Override
    protected void onStop() {
        mZXingView.stopCamera(); // 关闭摄像头预览，并且隐藏扫描框
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        mZXingView.onDestroy(); // 销毁二维码扫描控件
        super.onDestroy();
    }

    public void vibrate() {
        Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            vibrator.vibrate(VibrationEffect.createOneShot(200, VibrationEffect.DEFAULT_AMPLITUDE));
        } else {
            vibrator.vibrate(200);
        }
    }

    @OnClick({R2.id.btn_album})
    public void onClick(View v) {
        if (v.getId() == R.id.btn_album) {
//            if (Build.VERSION.SDK_INT >= 23) {
////                    if (!PermissionUtils.checkPermissionArray(this, needPermissions, ALBUM_REQUEST_CODE)) {
////                        return;
////                    }
//            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                Intent openAlbumIntent = new Intent(Intent.ACTION_GET_CONTENT);
                openAlbumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                startActivityForResult(openAlbumIntent, PHOTOZOOM);
            } else {
                Intent intent = new Intent(Intent.ACTION_PICK);
                intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                startActivityForResult(intent, PHOTOZOOM);
            }
//            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
//            intent.addCategory(Intent.CATEGORY_OPENABLE);
//            intent.setType("image/*");
//            startActivityForResult(intent, PHOTOZOOM);
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // 显示扫描框，并开始识别
        mZXingView.startSpotAndShowRect();
        if (requestCode == PHOTOZOOM) {
            if (data == null) {
                return;
            }
            Uri uri = data.getData();
            if (uri != null) {
//                Result result = parseQRcodeBitmap(uri);
//                String path = getPath(mContext, uri);
//                if (path == null) {
//                    return;
//                }
                Bitmap scanBitmap = BitmapUtil.decodeUri(this, uri, 500, 500);
                RxJavaUtils.executeAsyncTask(new RxAsyncTask<Bitmap, String>(scanBitmap) {
                    @Override
                    public String doInIOThread(Bitmap bitmap) {
                        return QRCodeDecoder.syncDecodeQRCode(bitmap);
                    }

                    @Override
                    public void doInUIThread(String result) {
                        if (result == null) {
                            showMessage("無法識別!");
                            killMyself();
                            return;
                        }
                        onScanQRCodeSuccess(result);
                        showMessage("扫描结果：" + result);
                    }
                });
//                if (result == null) {
//                    showMessage("無法識別!");
//                    killMyself();
//                    return;
//                }
//                onScanQRCodeSuccess(result.getText());
            }
        } else {
            finish();
        }
    }

    @Override
    public void showLoading(String message) {
        if (message != null) {
            LoadingDialog.showDialogForLoading(this, message, true);
        } else {
            LoadingDialog.showDialogForLoading(this);
        }
    }

    @Override
    public void hideLoading() {
        LoadingDialog.cancelDialogForLoading();
    }

    @Override
    public void showMessage(@NonNull String message) {
        Preconditions.checkNotNull(message);
        ArmsUtils.makeText(this, message);
    }

    @Override
    public void launchActivity(@NonNull Intent intent) {
        Preconditions.checkNotNull(intent);
        ArmsUtils.startActivity(intent);
    }

    @Override
    public void killMyself() {
        finish();
    }

    @Override
    public void onScanQRCodeSuccess(String result) {
        Log.i(TAG, "onScanQRCodeSuccess:" + result);
        vibrate();
//        mZXingView.startSpot();
        scanResult(result);
    }

    protected void scanResult(String result) {
        Intent intent = new Intent();
        intent.putExtra(QR_RESULT_CODE, result);
        setResult(ScanHelper.CALL_BACK_QR_RESULT, intent);
        CC.sendCCResult(CCUtil.getNavigateCallId(this), CCResult.success(QR_RESULT_CODE, result));
        killMyself();
    }


    @Override
    public void onCameraAmbientBrightnessChanged(boolean isDark) {
        // 这里是通过修改提示文案来展示环境是否过暗的状态，接入方也可以根据 isDark 的值来实现其他交互效果
        String tipText = mZXingView.getScanBoxView().getTipText();
        String ambientBrightnessTip = "\n環境過暗,請打開閃光燈";
        if (isDark) {
            if (!tipText.contains(ambientBrightnessTip)) {
                mZXingView.getScanBoxView().setTipText(tipText + ambientBrightnessTip);
            }
        } else {
            if (tipText.contains(ambientBrightnessTip)) {
                tipText = tipText.substring(0, tipText.indexOf(ambientBrightnessTip));
                mZXingView.getScanBoxView().setTipText(tipText);
            }
        }
    }

    @Override
    public void onScanQRCodeOpenCameraError() {
        showMessage("打開相機出錯!");
    }

    //解析二维码图片,返回结果封装在Result对象中
    private com.google.zxing.Result parseQRcodeBitmap(Uri uri) {
        String path = getPath(mContext, uri);
        if (path == null) {
            return null;
        }
        Bitmap scanBitmap = BitmapUtil.decodeUri(this, uri, 500, 500);
        RxJavaUtils.executeAsyncTask(new RxAsyncTask<Bitmap, String>(scanBitmap) {
            @Override
            public String doInIOThread(Bitmap bitmap) {
                return QRCodeDecoder.syncDecodeQRCode(bitmap);
            }

            @Override
            public void doInUIThread(String s) {
                showMessage("扫描结果：" + s);
            }
        });

        Hashtable<DecodeHintType, String> hints = new Hashtable<>();
        // 设置二维码内容的编码
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
        //新建一个RGBLuminanceSource对象，将bitmap图片传给此对象
        int width = scanBitmap.getWidth();
        int height = scanBitmap.getHeight();
        int[] pixels = new int[width * height];
        scanBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
        RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(width, height, pixels);
        //将图片转换成二进制图片
        BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(rgbLuminanceSource));
        //初始化解析对象
        Reader reader = new QRCodeReader();
        scanBitmap.recycle();
        //开始解析
        Result result = null;
        try {
            result = reader.decode(binaryBitmap, hints);
        } catch (NotFoundException e) {
            Log.e("hxy", "NotFoundException");
        } catch (ChecksumException e) {
            Log.e("hxy", "ChecksumException");
        } catch (FormatException e) {
            Log.e("hxy", "FormatException");
        }
        return result;
    }

    public static String getPath(final Context context, final Uri uri) {
        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };
                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri)) {
                return uri.getLastPathSegment();
            }
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return null;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }
}