/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.emergency.preferences;

import android.app.Activity;
import android.app.Fragment;
import android.content.ClipData;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract.DisplayPhoto;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListPopupWindow;
import android.widget.TextView;

import androidx.core.content.FileProvider;

import com.android.emergency.CircleFramedDrawable;
import com.android.emergency.R;
import com.android.settingslib.RestrictedLockUtilsInternal;

import libcore.io.Streams;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class EditUserPhotoController {
    private static final String TAG = "EditUserPhotoController";

    // It seems that this class generates custom request codes and they may
    // collide with ours, these values are very unlikely to have a conflict.
    private static final int REQUEST_CODE_CHOOSE_PHOTO = 10001;
    private static final int REQUEST_CODE_TAKE_PHOTO = 10002;
    private static final int REQUEST_CODE_CROP_PHOTO = 10003;

    private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg";
    private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
    private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
    private static final String NEW_USER_PHOTO_FILE_NAME = "NewUserPhoto.png";
    private static final String ACTION_CROP = "com.android.camera.action.CROP";
    private static final String FILE_PATH = "com.android.emergency.files";

    private final int mPhotoSize;

    private final Context mContext;
    private final Fragment mFragment;
    private final ImageView mImageView;

    private final Uri mPreCropPictureUri;
    private final Uri mCropPictureUri;
    private final Uri mTakePictureUri;

    private Bitmap mNewUserPhotoBitmap;
    private Drawable mNewUserPhotoDrawable;

    public EditUserPhotoController(Fragment fragment, ImageView view, Bitmap bitmap,
            Drawable drawable, boolean waiting) {
        mContext = view.getContext();
        mFragment = fragment;
        mImageView = view;
        mPreCropPictureUri = createTempImageUri(mContext, PRE_CROP_PICTURE_FILE_NAME, !waiting);
        mCropPictureUri = createTempImageUri(mContext, CROP_PICTURE_FILE_NAME, !waiting);
        mTakePictureUri = createTempImageUri(mContext, TAKE_PICTURE_FILE_NAME, !waiting);
        mPhotoSize = getPhotoSize(mContext);
        mImageView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                showUpdatePhotoPopup();
            }
        });
        mNewUserPhotoBitmap = bitmap;
        mNewUserPhotoDrawable = drawable;
    }

    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != Activity.RESULT_OK) {
            return false;
        }
        final Uri pictureUri = data != null && data.getData() != null
                ? data.getData() : mTakePictureUri;
        switch (requestCode) {
            case REQUEST_CODE_CROP_PHOTO:
                onPhotoCropped(pictureUri, true);
                return true;
            case REQUEST_CODE_TAKE_PHOTO:
            case REQUEST_CODE_CHOOSE_PHOTO:
                if (mTakePictureUri.equals(pictureUri)) {
                    cropPhoto(pictureUri);
                } else {
                    copyAndCropPhoto(pictureUri);
                }
                return true;
        }
        return false;
    }

    public Bitmap getNewUserPhotoBitmap() {
        return mNewUserPhotoBitmap;
    }

    public Drawable getNewUserPhotoDrawable() {
        return mNewUserPhotoDrawable;
    }

    private void showUpdatePhotoPopup() {
        final boolean canTakePhoto = canTakePhoto();
        final boolean canChoosePhoto = canChoosePhoto();

        if (!canTakePhoto && !canChoosePhoto) {
            return;
        }

        final Context context = mImageView.getContext();
        final List<EditUserPhotoController.RestrictedMenuItem> items = new ArrayList<>();

        if (canTakePhoto) {
            final String title = context.getString(R.string.user_image_take_photo);
            final Runnable action = new Runnable() {
                @Override
                public void run() {
                    takePhoto();
                }
            };
            items.add(new RestrictedMenuItem(context, title, UserManager.DISALLOW_SET_USER_ICON,
                    action));
        }

        if (canChoosePhoto) {
            final String title = context.getString(R.string.user_image_choose_photo);
            final Runnable action = new Runnable() {
                @Override
                public void run() {
                    choosePhoto();
                }
            };
            items.add(new RestrictedMenuItem(context, title, UserManager.DISALLOW_SET_USER_ICON,
                    action));
        }

        final ListPopupWindow listPopupWindow = new ListPopupWindow(context);

        listPopupWindow.setAnchorView(mImageView);
        listPopupWindow.setModal(true);
        listPopupWindow.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
        listPopupWindow.setAdapter(new RestrictedPopupMenuAdapter(context, items));

        final int width = Math.max(mImageView.getWidth(), context.getResources()
                .getDimensionPixelSize(R.dimen.update_user_photo_popup_min_width));
        listPopupWindow.setWidth(width);
        listPopupWindow.setDropDownGravity(Gravity.START);

        listPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                listPopupWindow.dismiss();
                final RestrictedMenuItem item =
                        (RestrictedMenuItem) parent.getAdapter().getItem(position);
                item.doAction();
            }
        });

        listPopupWindow.show();
    }

    private boolean canTakePhoto() {
        return mImageView.getContext().getPackageManager().queryIntentActivities(
                new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
                PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
    }

    private boolean canChoosePhoto() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        return mImageView.getContext().getPackageManager().queryIntentActivities(
                intent, 0).size() > 0;
    }

    private void takePhoto() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        appendOutputExtra(intent, mTakePictureUri);
        mFragment.startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
    }

    private void choosePhoto() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
        intent.setType("image/*");
        appendOutputExtra(intent, mTakePictureUri);
        mFragment.startActivityForResult(intent, REQUEST_CODE_CHOOSE_PHOTO);
    }

    private void copyAndCropPhoto(final Uri pictureUri) {
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                final ContentResolver cr = mContext.getContentResolver();
                try (InputStream in = cr.openInputStream(pictureUri);
                        OutputStream out = cr.openOutputStream(mPreCropPictureUri)) {
                    Streams.copy(in, out);
                } catch (IOException e) {
                    Log.w(TAG, "Failed to copy photo", e);
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                if (!mFragment.isAdded()) return;
                cropPhoto(mPreCropPictureUri);
            }
        }.execute();
    }

    private void cropPhoto(final Uri pictureUri) {
        Intent intent = new Intent(ACTION_CROP);
        intent.setDataAndType(pictureUri, "image/*");
        appendOutputExtra(intent, mCropPictureUri);
        appendCropExtras(intent);
        if (startSystemActivityForResult(intent, REQUEST_CODE_CROP_PHOTO)) {
            return;
        }
        onPhotoCropped(mTakePictureUri, false);
    }

    private boolean startSystemActivityForResult(Intent intent, int code) {
        ActivityInfo info = intent.resolveActivityInfo(mContext.getPackageManager(),
                PackageManager.MATCH_SYSTEM_ONLY);
        if (info == null) {
            Log.w(TAG, "No system package activity could be found for code " + code);
            return false;
        }
        intent.setPackage(info.packageName);
        mFragment.startActivityForResult(intent, code);
        return true;
    }

    private void appendOutputExtra(Intent intent, Uri pictureUri) {
        intent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, pictureUri));
    }

    private void appendCropExtras(Intent intent) {
        intent.putExtra("crop", "true");
        intent.putExtra("scale", true);
        intent.putExtra("scaleUpIfNeeded", true);
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", mPhotoSize);
        intent.putExtra("outputY", mPhotoSize);
    }

    private void onPhotoCropped(final Uri data, final boolean cropped) {
        new AsyncTask<Void, Void, Bitmap>() {
            @Override
            protected Bitmap doInBackground(Void... params) {
                if (cropped) {
                    InputStream imageStream = null;
                    try {
                        imageStream = mContext.getContentResolver()
                                .openInputStream(data);
                        return imageStream != null ? BitmapFactory.decodeStream(imageStream) : null;
                    } catch (FileNotFoundException fe) {
                        Log.w(TAG, "Cannot find image file", fe);
                        return null;
                    } finally {
                        if (imageStream != null) {
                            try {
                                imageStream.close();
                            } catch (IOException ioe) {
                                Log.w(TAG, "Cannot close image stream", ioe);
                            }
                        }
                    }
                } else {
                    // Scale and crop to a square aspect ratio
                    Bitmap fullImage = null;
                    try {
                        InputStream imageStream = mContext.getContentResolver()
                                .openInputStream(data);
                        fullImage = imageStream != null ? BitmapFactory.decodeStream(imageStream)
                                : null;
                    } catch (FileNotFoundException fe) {
                        Log.w(TAG, "Cannot find image file", fe);
                        return null;
                    }
                    if (fullImage != null) {
                        Bitmap croppedImage = Bitmap.createBitmap(mPhotoSize, mPhotoSize,
                                Config.ARGB_8888);
                        Canvas canvas = new Canvas(croppedImage);
                        final int squareSize = Math.min(fullImage.getWidth(),
                                fullImage.getHeight());
                        final int left = (fullImage.getWidth() - squareSize) / 2;
                        final int top = (fullImage.getHeight() - squareSize) / 2;
                        Rect rectSource = new Rect(left, top,
                                left + squareSize, top + squareSize);
                        Rect rectDest = new Rect(0, 0, mPhotoSize, mPhotoSize);
                        Paint paint = new Paint();
                        canvas.drawBitmap(fullImage, rectSource, rectDest, paint);
                        return croppedImage;
                    } else {
                        return null;
                    }
                }
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                if (bitmap != null) {
                    mNewUserPhotoBitmap = bitmap;
                    mNewUserPhotoDrawable = CircleFramedDrawable
                            .getInstance(mImageView.getContext(), mNewUserPhotoBitmap);
                    mImageView.setImageDrawable(mNewUserPhotoDrawable);
                }
                new File(mContext.getCacheDir(), TAKE_PICTURE_FILE_NAME).delete();
                new File(mContext.getCacheDir(), CROP_PICTURE_FILE_NAME).delete();
            }
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
    }

    private static int getPhotoSize(Context context) {
        Cursor cursor = context.getContentResolver().query(
                DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
                new String[]{DisplayPhoto.DISPLAY_MAX_DIM}, null, null, null);
        try {
            cursor.moveToFirst();
            return cursor.getInt(0);
        } finally {
            cursor.close();
        }
    }

    private Uri createTempImageUri(Context context, String fileName, boolean purge) {
        final File folder = context.getCacheDir();
        folder.mkdirs();
        final File fullPath = new File(folder, fileName);
        if (purge) {
            fullPath.delete();
        }
        return FileProvider.getUriForFile(context, FILE_PATH, fullPath);
    }

    File saveNewUserPhotoBitmap() {
        if (mNewUserPhotoBitmap == null) {
            return null;
        }
        try {
            File file = new File(mContext.getCacheDir(), NEW_USER_PHOTO_FILE_NAME);
            OutputStream os = new FileOutputStream(file);
            mNewUserPhotoBitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
            os.flush();
            os.close();
            return file;
        } catch (IOException e) {
            Log.e(TAG, "Cannot create temp file", e);
        }
        return null;
    }

    static Bitmap loadNewUserPhotoBitmap(File file) {
        return BitmapFactory.decodeFile(file.getAbsolutePath());
    }

    void removeNewUserPhotoBitmapFile() {
        new File(mContext.getCacheDir(), NEW_USER_PHOTO_FILE_NAME).delete();
    }

    private static final class RestrictedMenuItem {
        private final Context mContext;
        private final String mTitle;
        private final Runnable mAction;
        private final RestrictedLockUtilsInternal.EnforcedAdmin mAdmin;
        // Restriction may be set by system or something else via UserManager.setUserRestriction().
        private final boolean mIsRestrictedByBase;

        /**
         * The menu item, used for popup menu. Any element of such a menu can be disabled by admin.
         *
         * @param context     A context.
         * @param title       The title of the menu item.
         * @param restriction The restriction, that if is set, blocks the menu item.
         * @param action      The action on menu item click.
         */
        public RestrictedMenuItem(Context context, String title, String restriction,
                Runnable action) {
            mContext = context;
            mTitle = title;
            mAction = action;

            final int myUserId = UserHandle.myUserId();
            mAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context,
                    restriction, myUserId);
            mIsRestrictedByBase = RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
                    restriction, myUserId);
        }

        @Override
        public String toString() {
            return mTitle;
        }

        final void doAction() {
            if (isRestrictedByBase()) {
                return;
            }

            if (isRestrictedByAdmin()) {
                RestrictedLockUtilsInternal.sendShowAdminSupportDetailsIntent(mContext, mAdmin);
                return;
            }

            mAction.run();
        }

        final boolean isRestrictedByAdmin() {
            return mAdmin != null;
        }

        final boolean isRestrictedByBase() {
            return mIsRestrictedByBase;
        }
    }

    /**
     * Provide this adapter to ListPopupWindow.setAdapter() to have a popup window menu, where
     * any element can be restricted by admin (profile owner or device owner).
     */
    private static final class RestrictedPopupMenuAdapter extends ArrayAdapter<RestrictedMenuItem> {
        public RestrictedPopupMenuAdapter(Context context, List<RestrictedMenuItem> items) {
            super(context, R.layout.restricted_popup_menu_item, R.id.text, items);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final View view = super.getView(position, convertView, parent);
            final RestrictedMenuItem item = getItem(position);
            final TextView text = (TextView) view.findViewById(R.id.text);
            final ImageView image = (ImageView) view.findViewById(R.id.restricted_icon);

            text.setEnabled(!item.isRestrictedByAdmin() && !item.isRestrictedByBase());
            image.setVisibility(item.isRestrictedByAdmin() && !item.isRestrictedByBase() ?
                    ImageView.VISIBLE : ImageView.GONE);

            return view;
        }
    }
}
