package com.sw926.imagefileselector;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import androidx.fragment.app.Fragment;
import androidx.core.content.FileProvider;
import android.text.TextUtils;

import java.io.File;

@SuppressWarnings("unused")
public class ImageCropper {


    public enum CropperErrorResult {
        error,
        canceled,
        notSupport
    }

    private static final String TAG = ImageCropper.class.getSimpleName();

    private static final String IMAGE_CROPPER_BUNDLE = "IMAGE_CROPPER_BUNDLE";

    private int mOutPutX = -1;
    private int mOutPutY = -1;
    private int mAspectX = -1;
    private int mAspectY = -1;
    private boolean mScale = true;

    private File mSrcFile = null;
    private File mOutFile = null;
    private int mRequestCode = -1;

    /**
     * 记录裁切过程中产生的临时文件,裁切完成后进行删除
     */
    private File mTempFile = null;

    private ImageCropperCallback mCallback = null;

    private Fragment fragment = null;
    private Activity activity = null;

    public void setOutPut(int width, int height) {
        mOutPutX = width;
        mOutPutY = height;
    }

    public void setOutPutAspect(int width, int height) {
        mAspectX = width;
        mAspectY = height;
    }

    void setScale(boolean scale) {
        mScale = scale;
    }

    public void setCallback(ImageCropperCallback callback) {
        mCallback = callback;
    }

    private Context getContext() {
        if (activity != null) {
            return activity;
        }
        if (fragment != null) {
            return fragment.getContext();
        }
        return null;
    }

    public void onSaveInstanceState(Bundle outState) {
        Bundle bundle = new Bundle();
        bundle.putInt("outputX", mOutPutX);
        bundle.putInt("outputY", mOutPutY);
        bundle.putInt("aspectX", mAspectX);
        bundle.putInt("aspectY", mAspectY);
        bundle.putBoolean("scale", mScale);
        bundle.putSerializable("outFile", mOutFile);
        bundle.putSerializable("srcFile", mSrcFile);
        bundle.putSerializable("tempFile", mTempFile);
        outState.putBundle(IMAGE_CROPPER_BUNDLE, bundle);
    }

    public void onRestoreInstanceState(Bundle savedInstanceState) {
        if (savedInstanceState != null && savedInstanceState.containsKey(IMAGE_CROPPER_BUNDLE)) {
            Bundle bundle = savedInstanceState.getBundle(IMAGE_CROPPER_BUNDLE);
            if (bundle != null) {
                mOutPutX = bundle.getInt("outputX");
                mOutPutY = bundle.getInt("outputY");
                mAspectX = bundle.getInt("aspectX");
                mAspectY = bundle.getInt("aspectY");
                mScale = bundle.getBoolean("scale");
                mOutFile = (File) bundle.getSerializable("outFile");
                mSrcFile = (File) bundle.getSerializable("srcFile");
                mTempFile = (File) bundle.getSerializable("tempFile");
            }
        }
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (mRequestCode > 0 && requestCode == mRequestCode) {
            if (resultCode == Activity.RESULT_CANCELED) {
                if (mCallback != null) {
                    mCallback.onError(CropperErrorResult.canceled);
                }
                return;
            }
            if (mTempFile != null && mTempFile.exists()) {
                AppLogger.i(TAG, "delete temp file: " + mTempFile.getPath());
                mTempFile.delete();
            }
            if (mOutFile != null && mOutFile.exists()) {
                AppLogger.i(TAG, "crop success output file: " + mOutFile.getPath());
                if (mCallback != null) {
                    mCallback.onSuccess(mOutFile.getPath());
                }
                return;
            }

            Context context = getContext();
            if (context != null && data != null) {
                if (data.getData() != null) {
                    String path = Compatibility.getPath(context, data.getData());
                    if (!TextUtils.isEmpty(path)) {
                        File outputFile = new File(path);
                        if (outputFile.exists()) {
                            AppLogger.i(TAG, "crop success output file:" + path);
                            if (mCallback != null) {
                                mCallback.onSuccess(path);
                            }
                            return;
                        }
                    }
                }

                Bitmap bitmap = data.getParcelableExtra("data");
                if (bitmap != null) {
                    File outputFile = CommonUtils.generateExternalImageCacheFile(context, ".jpg");
                    ImageUtils.saveBitmap(bitmap, outputFile.getPath(), Bitmap.CompressFormat.JPEG, 80);
                    AppLogger.i(TAG, "create output file from data: " + outputFile.getPath());
                    if (mCallback != null) {
                        mCallback.onSuccess(outputFile.getPath());
                    }
                    return;
                }
            }
            if (mCallback != null) {
                mCallback.onError(CropperErrorResult.error);
            }
        }
    }

    public void cropImage(Activity activity, String srcFile, int requestCode) {
        this.fragment = null;
        this.activity = activity;
        this.mRequestCode = requestCode;
        cropImage(srcFile);
    }

    public void cropImage(Fragment fragment, String srcFile, int requestCode) {
        this.fragment = fragment;
        this.activity = null;
        this.mRequestCode = requestCode;
        cropImage(srcFile);
    }

    private void cropImage(String srcFile) {
        try {
            AppLogger.i(TAG, "------------------ start crop file ---------------");

            Context context = getContext();
            if (context == null) {
                AppLogger.e(TAG, "fragment or activity is null");
                if (mCallback != null) {
                    mCallback.onError(CropperErrorResult.error);
                }
                return;
            }

            File inputFile = new File(srcFile);
            if (!inputFile.exists()) {
                AppLogger.e(TAG, "input file not exists");
                if (mCallback != null) {
                    mCallback.onError(CropperErrorResult.error);
                }
                return;
            }

            File outFile = CommonUtils.generateExternalImageCacheFile(context, ".jpg");
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            if (outFile.exists()) {
                outFile.delete();
            }
            AppLogger.i(TAG, "set output file: " + outFile.getPath());


            mSrcFile = inputFile;
            mOutFile = outFile;

            String providerName = getContext().getPackageName() + ".com.sw926.imagefileselector.provider";
            Uri uri;
            if (inputFile.getPath().contains("%")) {
                String ext = srcFile.substring(srcFile.lastIndexOf("."));
                mTempFile = CommonUtils.generateExternalImageCacheFile(context, ext);
                CommonUtils.copy(inputFile, mTempFile);

                uri = FileProvider.getUriForFile(context, providerName, mTempFile);
                AppLogger.w(TAG, "use temp file:" + mTempFile.getPath());
            } else {
                uri = FileProvider.getUriForFile(context, providerName, inputFile);
            }

            Intent intent = new Intent("com.android.camera.action.CROP");
            intent.setDataAndType(uri, "image/*");
            intent.putExtra("crop", "true");
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

            if (mAspectX > 0 && mAspectY > 0) {
                intent.putExtra("aspectX", mAspectX);
                intent.putExtra("aspectY", mAspectY);
            }
            if (mOutPutX > 0 && mOutPutY > 0) {
                intent.putExtra("outputX", mOutPutX);
                intent.putExtra("outputY", mOutPutY);
            }

            if (mScale) {
                intent.putExtra("scale", true);
                intent.putExtra("scaleUpIfNeeded", true);// 黑边
            }
            if (Compatibility.scaleUpIfNeeded4Black()) {
                intent.putExtra("scaleUpIfNeeded", true);
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outFile));
            if (Compatibility.shouldReturnCropData()) {
                intent.putExtra("return-data", true);
            }
            if (activity != null) {
                try {
                    activity.startActivityForResult(intent, mRequestCode);
                } catch (ActivityNotFoundException e) {
                    if (mCallback != null) {
                        mCallback.onError(CropperErrorResult.notSupport);
                    }
                }
            }

            if (fragment != null) {
                try {
                    fragment.startActivityForResult(intent, mRequestCode);
                } catch (ActivityNotFoundException e) {
                    if (mCallback != null) {
                        mCallback.onError(CropperErrorResult.notSupport);
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            if (mCallback != null) {
                mCallback.onError(CropperErrorResult.error);
            }
        }
    }

    public interface ImageCropperCallback {
        void onError(CropperErrorResult result);

        void onSuccess(String outputFile);
    }


}