/*
 * Copyright (C) 2010 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.contacts;

import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.support.v4.graphics.drawable.IconCompat;
import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
import android.support.v4.os.BuildCompat;
import android.telecom.PhoneAccount;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;

import com.android.contacts.ContactPhotoManager.DefaultImageRequest;
import com.android.contacts.lettertiles.LetterTileDrawable;
import com.android.contacts.util.BitmapUtil;
import com.android.contacts.util.ImplicitIntentsUtil;

/**
 * Constructs shortcut intents.
 */
public class ShortcutIntentBuilder {

    private static final String[] CONTACT_COLUMNS = {
        Contacts.DISPLAY_NAME,
        Contacts.PHOTO_ID,
        Contacts.LOOKUP_KEY
    };

    private static final int CONTACT_DISPLAY_NAME_COLUMN_INDEX = 0;
    private static final int CONTACT_PHOTO_ID_COLUMN_INDEX = 1;
    private static final int CONTACT_LOOKUP_KEY_COLUMN_INDEX = 2;

    private static final String[] PHONE_COLUMNS = {
        Phone.DISPLAY_NAME,
        Phone.PHOTO_ID,
        Phone.NUMBER,
        Phone.TYPE,
        Phone.LABEL,
        Phone.LOOKUP_KEY
    };

    private static final int PHONE_DISPLAY_NAME_COLUMN_INDEX = 0;
    private static final int PHONE_PHOTO_ID_COLUMN_INDEX = 1;
    private static final int PHONE_NUMBER_COLUMN_INDEX = 2;
    private static final int PHONE_TYPE_COLUMN_INDEX = 3;
    private static final int PHONE_LABEL_COLUMN_INDEX = 4;
    private static final int PHONE_LOOKUP_KEY_COLUMN_INDEX = 5;

    private static final String[] PHOTO_COLUMNS = {
        Photo.PHOTO,
    };

    private static final int PHOTO_PHOTO_COLUMN_INDEX = 0;

    private static final String PHOTO_SELECTION = Photo._ID + "=?";

    private final OnShortcutIntentCreatedListener mListener;
    private final Context mContext;
    private int mIconSize;
    private final int mIconDensity;
    private final int mOverlayTextBackgroundColor;
    private final Resources mResources;

    /**
     * This is a hidden API of the launcher in JellyBean that allows us to disable the animation
     * that it would usually do, because it interferes with our own animation for QuickContact.
     * This is needed since some versions of the launcher override the intent flags and therefore
     * ignore Intent.FLAG_ACTIVITY_NO_ANIMATION.
     */
    public static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION =
            "com.android.launcher.intent.extra.shortcut.INGORE_LAUNCH_ANIMATION";

    /**
     * Listener interface.
     */
    public interface OnShortcutIntentCreatedListener {

        /**
         * Callback for shortcut intent creation.
         *
         * @param uri the original URI for which the shortcut intent has been
         *            created.
         * @param shortcutIntent resulting shortcut intent.
         */
        void onShortcutIntentCreated(Uri uri, Intent shortcutIntent);
    }

    public ShortcutIntentBuilder(Context context, OnShortcutIntentCreatedListener listener) {
        mContext = context;
        mListener = listener;

        mResources = context.getResources();
        final ActivityManager am = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        mIconSize = mResources.getDimensionPixelSize(R.dimen.shortcut_icon_size);
        if (mIconSize == 0) {
            mIconSize = am.getLauncherLargeIconSize();
        }
        mIconDensity = am.getLauncherLargeIconDensity();
        mOverlayTextBackgroundColor = mResources.getColor(R.color.shortcut_overlay_text_background);
    }

    public void createContactShortcutIntent(Uri contactUri) {
        new ContactLoadingAsyncTask(contactUri).execute();
    }

    public void createPhoneNumberShortcutIntent(Uri dataUri, String shortcutAction) {
        new PhoneNumberLoadingAsyncTask(dataUri, shortcutAction).execute();
    }

    /**
     * An asynchronous task that loads name, photo and other data from the database.
     */
    private abstract class LoadingAsyncTask extends AsyncTask<Void, Void, Void> {
        protected Uri mUri;
        protected String mContentType;
        protected String mDisplayName;
        protected String mLookupKey;
        protected byte[] mBitmapData;
        protected long mPhotoId;

        public LoadingAsyncTask(Uri uri) {
            mUri = uri;
        }

        @Override
        protected Void doInBackground(Void... params) {
            mContentType = mContext.getContentResolver().getType(mUri);
            loadData();
            loadPhoto();
            return null;
        }

        protected abstract void loadData();

        private void loadPhoto() {
            if (mPhotoId == 0) {
                return;
            }

            ContentResolver resolver = mContext.getContentResolver();
            Cursor cursor = resolver.query(Data.CONTENT_URI, PHOTO_COLUMNS, PHOTO_SELECTION,
                    new String[] { String.valueOf(mPhotoId) }, null);
            if (cursor != null) {
                try {
                    if (cursor.moveToFirst()) {
                        mBitmapData = cursor.getBlob(PHOTO_PHOTO_COLUMN_INDEX);
                    }
                } finally {
                    cursor.close();
                }
            }
        }
    }

    private final class ContactLoadingAsyncTask extends LoadingAsyncTask {
        public ContactLoadingAsyncTask(Uri uri) {
            super(uri);
        }

        @Override
        protected void loadData() {
            ContentResolver resolver = mContext.getContentResolver();
            Cursor cursor = resolver.query(mUri, CONTACT_COLUMNS, null, null, null);
            if (cursor != null) {
                try {
                    if (cursor.moveToFirst()) {
                        mDisplayName = cursor.getString(CONTACT_DISPLAY_NAME_COLUMN_INDEX);
                        mPhotoId = cursor.getLong(CONTACT_PHOTO_ID_COLUMN_INDEX);
                        mLookupKey = cursor.getString(CONTACT_LOOKUP_KEY_COLUMN_INDEX);
                    }
                } finally {
                    cursor.close();
                }
            }
        }
        @Override
        protected void onPostExecute(Void result) {
            createContactShortcutIntent(mUri, mContentType, mDisplayName, mLookupKey, mBitmapData);
        }
    }

    private final class PhoneNumberLoadingAsyncTask extends LoadingAsyncTask {
        private final String mShortcutAction;
        private String mPhoneNumber;
        private int mPhoneType;
        private String mPhoneLabel;

        public PhoneNumberLoadingAsyncTask(Uri uri, String shortcutAction) {
            super(uri);
            mShortcutAction = shortcutAction;
        }

        @Override
        protected void loadData() {
            ContentResolver resolver = mContext.getContentResolver();
            Cursor cursor = resolver.query(mUri, PHONE_COLUMNS, null, null, null);
            if (cursor != null) {
                try {
                    if (cursor.moveToFirst()) {
                        mDisplayName = cursor.getString(PHONE_DISPLAY_NAME_COLUMN_INDEX);
                        mPhotoId = cursor.getLong(PHONE_PHOTO_ID_COLUMN_INDEX);
                        mPhoneNumber = cursor.getString(PHONE_NUMBER_COLUMN_INDEX);
                        mPhoneType = cursor.getInt(PHONE_TYPE_COLUMN_INDEX);
                        mPhoneLabel = cursor.getString(PHONE_LABEL_COLUMN_INDEX);
                        mLookupKey = cursor.getString(PHONE_LOOKUP_KEY_COLUMN_INDEX);
                    }
                } finally {
                    cursor.close();
                }
            }
        }

        @Override
        protected void onPostExecute(Void result) {
            createPhoneNumberShortcutIntent(mUri, mDisplayName, mLookupKey, mBitmapData,
                    mPhoneNumber, mPhoneType, mPhoneLabel, mShortcutAction);
        }
    }

    private Drawable getPhotoDrawable(byte[] bitmapData, String displayName, String lookupKey) {
        if (bitmapData != null) {
            Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length, null);
            return new BitmapDrawable(mContext.getResources(), bitmap);
        } else {
            final DefaultImageRequest request = new DefaultImageRequest(displayName, lookupKey,
                    false);
            if (BuildCompat.isAtLeastO()) {
                // On O, scale the image down to add the padding needed by AdaptiveIcons.
                request.scale = LetterTileDrawable.getAdaptiveIconScale();
            }
            return ContactPhotoManager.getDefaultAvatarDrawableForContact(mContext.getResources(),
                    false, request);
        }
    }

    private void createContactShortcutIntent(Uri contactUri, String contentType, String displayName,
            String lookupKey, byte[] bitmapData) {
        Intent intent = null;
        if (TextUtils.isEmpty(displayName)) {
            displayName = mContext.getResources().getString(R.string.missing_name);
        }
        if (BuildCompat.isAtLeastO()) {
            final long contactId = ContentUris.parseId(contactUri);
            final ShortcutManager sm = (ShortcutManager)
                    mContext.getSystemService(Context.SHORTCUT_SERVICE);
            final DynamicShortcuts dynamicShortcuts = new DynamicShortcuts(mContext);
            final ShortcutInfo shortcutInfo = dynamicShortcuts.getQuickContactShortcutInfo(
                    contactId, lookupKey, displayName);
            if (shortcutInfo != null) {
                intent = sm.createShortcutResultIntent(shortcutInfo);
            }
        }
        final Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey);

        final Intent shortcutIntent = ImplicitIntentsUtil.getIntentForQuickContactLauncherShortcut(
                mContext, contactUri);

        intent = intent == null ? new Intent() : intent;

        final Bitmap icon = generateQuickContactIcon(drawable);
        if (BuildCompat.isAtLeastO()) {
            final IconCompat compatIcon = IconCompat.createWithAdaptiveBitmap(icon);
            compatIcon.addToShortcutIntent(intent, null, mContext);
        } else {
            intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
        }
        intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
        intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, displayName);

        mListener.onShortcutIntentCreated(contactUri, intent);
    }

    private void createPhoneNumberShortcutIntent(Uri uri, String displayName, String lookupKey,
            byte[] bitmapData, String phoneNumber, int phoneType, String phoneLabel,
            String shortcutAction) {
        final Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey);
        final Bitmap icon;
        final Uri phoneUri;
        final String shortcutName;
        if (TextUtils.isEmpty(displayName)) {
            displayName = mContext.getResources().getString(R.string.missing_name);
        }

        if (Intent.ACTION_CALL.equals(shortcutAction)) {
            // Make the URI a direct tel: URI so that it will always continue to work
            phoneUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null);
            icon = generatePhoneNumberIcon(drawable, phoneType, phoneLabel,
                    R.drawable.quantum_ic_phone_vd_theme_24);
            shortcutName = mContext.getResources()
                    .getString(R.string.call_by_shortcut, displayName);
        } else {
            phoneUri = Uri.fromParts(ContactsUtils.SCHEME_SMSTO, phoneNumber, null);
            icon = generatePhoneNumberIcon(drawable, phoneType, phoneLabel,
                    R.drawable.quantum_ic_message_vd_theme_24);
            shortcutName = mContext.getResources().getString(R.string.sms_by_shortcut, displayName);
        }

        final Intent shortcutIntent = new Intent(shortcutAction, phoneUri);
        shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        Intent intent = null;
        IconCompat compatAdaptiveIcon = null;
        if (BuildCompat.isAtLeastO()) {
            compatAdaptiveIcon = IconCompat.createWithAdaptiveBitmap(icon);
            final ShortcutManager sm = (ShortcutManager)
                    mContext.getSystemService(Context.SHORTCUT_SERVICE);
            final String id = shortcutAction + lookupKey + phoneUri.toString().hashCode();
            final DynamicShortcuts dynamicShortcuts = new DynamicShortcuts(mContext);
            final ShortcutInfo shortcutInfo = dynamicShortcuts.getActionShortcutInfo(
                    id, displayName, shortcutIntent, compatAdaptiveIcon.toIcon());
            if (shortcutInfo != null) {
                intent = sm.createShortcutResultIntent(shortcutInfo);
            }
        }

        intent = intent == null ? new Intent() : intent;
        // This will be non-null in O and above.
        if (compatAdaptiveIcon != null) {
            compatAdaptiveIcon.addToShortcutIntent(intent, null, mContext);
        } else {
            intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
        }
        intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
        intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortcutName);

        mListener.onShortcutIntentCreated(uri, intent);
    }

    private Bitmap generateQuickContactIcon(Drawable photo) {
        // Setup the drawing classes
        Bitmap bitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);

        // Copy in the photo
        Rect dst = new Rect(0,0, mIconSize, mIconSize);
        photo.setBounds(dst);
        photo.draw(canvas);

        // Don't put a rounded border on an icon for O
        if (BuildCompat.isAtLeastO()) {
            return bitmap;
        }

        // Draw the icon with a rounded border
        RoundedBitmapDrawable roundedDrawable =
                RoundedBitmapDrawableFactory.create(mResources, bitmap);
        roundedDrawable.setAntiAlias(true);
        roundedDrawable.setCornerRadius(mIconSize / 2);
        Bitmap roundedBitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
        canvas.setBitmap(roundedBitmap);
        roundedDrawable.setBounds(dst);
        roundedDrawable.draw(canvas);
        canvas.setBitmap(null);

        return roundedBitmap;
    }

    /**
     * Generates a phone number shortcut icon. Adds an overlay describing the type of the phone
     * number, and if there is a photo also adds the call action icon.
     */
    private Bitmap generatePhoneNumberIcon(Drawable photo, int phoneType, String phoneLabel,
            int actionResId) {
        final Resources r = mContext.getResources();
        final float density = r.getDisplayMetrics().density;

        final Drawable phoneDrawable = r.getDrawableForDensity(actionResId, mIconDensity);
        // These icons have the same height and width so either is fine for the size.
        final Bitmap phoneIcon =
                BitmapUtil.drawableToBitmap(phoneDrawable, phoneDrawable.getIntrinsicHeight());

        Bitmap icon = generateQuickContactIcon(photo);
        Canvas canvas = new Canvas(icon);

        // Copy in the photo
        Paint photoPaint = new Paint();
        photoPaint.setDither(true);
        photoPaint.setFilterBitmap(true);
        Rect dst = new Rect(0, 0, mIconSize, mIconSize);

        // Create an overlay for the phone number type if we're pre-O. O created shortcuts have the
        // app badge which overlaps the type overlay.
        CharSequence overlay = Phone.getTypeLabel(r, phoneType, phoneLabel);
        if (!BuildCompat.isAtLeastO() && overlay != null) {
            TextPaint textPaint = new TextPaint(
                    Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
            textPaint.setTextSize(r.getDimension(R.dimen.shortcut_overlay_text_size));
            textPaint.setColor(r.getColor(R.color.textColorIconOverlay));
            textPaint.setShadowLayer(4f, 0, 2f, r.getColor(R.color.textColorIconOverlayShadow));

            final FontMetricsInt fmi = textPaint.getFontMetricsInt();

            // First fill in a darker background around the text to be drawn
            final Paint workPaint = new Paint();
            workPaint.setColor(mOverlayTextBackgroundColor);
            workPaint.setStyle(Paint.Style.FILL);
            final int textPadding = r
                    .getDimensionPixelOffset(R.dimen.shortcut_overlay_text_background_padding);
            final int textBandHeight = (fmi.descent - fmi.ascent) + textPadding * 2;
            dst.set(0, mIconSize - textBandHeight, mIconSize, mIconSize);
            canvas.drawRect(dst, workPaint);

            overlay = TextUtils.ellipsize(overlay, textPaint, mIconSize, TruncateAt.END);
            final float textWidth = textPaint.measureText(overlay, 0, overlay.length());
            canvas.drawText(overlay, 0, overlay.length(), (mIconSize - textWidth) / 2, mIconSize
                    - fmi.descent - textPadding, textPaint);
        }

        // Draw the phone action icon as an overlay
        int iconWidth = icon.getWidth();
        if (BuildCompat.isAtLeastO()) {
            // On O we need to calculate where the phone icon goes slightly differently. The whole
            // canvas area is 108dp, a centered circle with a diameter of 66dp is the "safe zone".
            // So we start the drawing the phone icon at
            // 108dp - 21 dp (distance from right edge of safe zone to the edge of the canvas)
            // - 24 dp (size of the phone icon) on the x axis (left)
            // The y axis is simply 21dp for the distance to the safe zone (top).
            // See go/o-icons-eng for more details and a handy picture.
            final int left = (int) (mIconSize - (45 * density));
            final int top = (int) (21 * density);
            canvas.drawBitmap(phoneIcon, left, top, photoPaint);
        } else {
            dst.set(iconWidth - ((int) (20 * density)), -1,
                    iconWidth, ((int) (19 * density)));
            canvas.drawBitmap(phoneIcon, null, dst, photoPaint);
        }

        canvas.setBitmap(null);
        return icon;
    }
}
