/*
 * Copyright (C) 2016 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.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.PersistableBundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.support.annotation.VisibleForTesting;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.os.BuildCompat;
import android.util.Log;

import com.android.contacts.activities.RequestPermissionsActivity;
import com.android.contacts.compat.CompatUtils;
import com.android.contacts.lettertiles.LetterTileDrawable;
import com.android.contacts.util.BitmapUtil;
import com.android.contacts.util.ImplicitIntentsUtil;
import com.android.contacts.util.PermissionsUtil;
import com.android.contactsbind.experiments.Flags;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * This class creates and updates the dynamic shortcuts displayed on the Nexus launcher for the
 * Contacts app.
 *
 * Currently it adds shortcuts for the top 3 contacts in the {@link Contacts#CONTENT_STREQUENT_URI}
 *
 * Usage: DynamicShortcuts.initialize should be called during Application creation. This will
 * schedule a Job to keep the shortcuts up-to-date so no further interactions should be necessary.
 */
@TargetApi(Build.VERSION_CODES.N_MR1)
public class DynamicShortcuts {
    private static final String TAG = "DynamicShortcuts";

    // Must be the same as shortcutId in res/xml/shortcuts.xml
    // Note: This doesn't fit very well because this is a "static" shortcut but it's still the most
    // sensible place to put it right now.
    public static final String SHORTCUT_ADD_CONTACT = "shortcut-add-contact";

    // Note the Nexus launcher automatically truncates shortcut labels if they exceed these limits
    // however, we implement our own truncation in case the shortcut is shown on a launcher that
    // has different behavior
    private static final int SHORT_LABEL_MAX_LENGTH = 12;
    private static final int LONG_LABEL_MAX_LENGTH = 30;
    private static final int MAX_SHORTCUTS = 3;

    private static final String EXTRA_SHORTCUT_TYPE = "extraShortcutType";

    // Because pinned shortcuts persist across app upgrades these values should not be changed
    // though new ones may be added
    private static final int SHORTCUT_TYPE_UNKNOWN = 0;
    private static final int SHORTCUT_TYPE_CONTACT_URI = 1;
    private static final int SHORTCUT_TYPE_ACTION_URI = 2;

    @VisibleForTesting
    static final String[] PROJECTION = new String[] {
            Contacts._ID, Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME_PRIMARY
    };

    private final Context mContext;

    private final ContentResolver mContentResolver;
    private final ShortcutManager mShortcutManager;
    private int mShortLabelMaxLength = SHORT_LABEL_MAX_LENGTH;
    private int mLongLabelMaxLength = LONG_LABEL_MAX_LENGTH;
    private int mIconSize;
    private final int mContentChangeMinUpdateDelay;
    private final int mContentChangeMaxUpdateDelay;
    private final JobScheduler mJobScheduler;

    public DynamicShortcuts(Context context) {
        this(context, context.getContentResolver(), (ShortcutManager)
                context.getSystemService(Context.SHORTCUT_SERVICE),
                (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE));
    }

    @VisibleForTesting
    public DynamicShortcuts(Context context, ContentResolver contentResolver,
            ShortcutManager shortcutManager, JobScheduler jobScheduler) {
        mContext = context;
        mContentResolver = contentResolver;
        mShortcutManager = shortcutManager;
        mJobScheduler = jobScheduler;
        mContentChangeMinUpdateDelay = Flags.getInstance()
                .getInteger(Experiments.DYNAMIC_MIN_CONTENT_CHANGE_UPDATE_DELAY_MILLIS);
        mContentChangeMaxUpdateDelay = Flags.getInstance()
                .getInteger(Experiments.DYNAMIC_MAX_CONTENT_CHANGE_UPDATE_DELAY_MILLIS);
        final ActivityManager am = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        mIconSize = context.getResources().getDimensionPixelSize(R.dimen.shortcut_icon_size);
        if (mIconSize == 0) {
            mIconSize = am.getLauncherLargeIconSize();
        }
    }

    @VisibleForTesting
    void setShortLabelMaxLength(int length) {
        this.mShortLabelMaxLength = length;
    }

    @VisibleForTesting
    void setLongLabelMaxLength(int length) {
        this.mLongLabelMaxLength = length;
    }

    @VisibleForTesting
    void refresh() {
        // Guard here in addition to initialize because this could be run by the JobScheduler
        // after permissions are revoked (maybe)
        if (!hasRequiredPermissions()) return;

        final List<ShortcutInfo> shortcuts = getStrequentShortcuts();
        mShortcutManager.setDynamicShortcuts(shortcuts);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "set dynamic shortcuts " + shortcuts);
        }
        updatePinned();
    }

    @VisibleForTesting
    void updatePinned() {
        final List<ShortcutInfo> updates = new ArrayList<>();
        final List<String> removedIds = new ArrayList<>();
        final List<String> enable = new ArrayList<>();

        for (ShortcutInfo shortcut : mShortcutManager.getPinnedShortcuts()) {
            final PersistableBundle extras = shortcut.getExtras();

            if (extras == null || extras.getInt(EXTRA_SHORTCUT_TYPE, SHORTCUT_TYPE_UNKNOWN) !=
                    SHORTCUT_TYPE_CONTACT_URI) {
                continue;
            }

            // The contact ID may have changed but that's OK because it is just an optimization
            final long contactId = extras.getLong(Contacts._ID);

            final ShortcutInfo update = createShortcutForUri(
                    Contacts.getLookupUri(contactId, shortcut.getId()));
            if (update != null) {
                updates.add(update);
                if (!shortcut.isEnabled()) {
                    // Handle the case that a contact is disabled because it doesn't exist but
                    // later is created (for instance by a sync)
                    enable.add(update.getId());
                }
            } else if (shortcut.isEnabled()) {
                removedIds.add(shortcut.getId());
            }
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "updating " + updates);
            Log.d(TAG, "enabling " + enable);
            Log.d(TAG, "disabling " + removedIds);
        }

        mShortcutManager.updateShortcuts(updates);
        mShortcutManager.enableShortcuts(enable);
        mShortcutManager.disableShortcuts(removedIds,
                mContext.getString(R.string.dynamic_shortcut_contact_removed_message));
    }

    private ShortcutInfo createShortcutForUri(Uri contactUri) {
        final Cursor cursor = mContentResolver.query(contactUri, PROJECTION, null, null, null);
        if (cursor == null) return null;

        try {
            if (cursor.moveToFirst()) {
                return createShortcutFromRow(cursor);
            }
        } finally {
            cursor.close();
        }
        return null;
    }

    public List<ShortcutInfo> getStrequentShortcuts() {
        // The limit query parameter doesn't seem to work for this uri but we'll leave it because in
        // case it does work on some phones or platform versions.
        final Uri uri = Contacts.CONTENT_STREQUENT_URI.buildUpon()
                .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY,
                        String.valueOf(MAX_SHORTCUTS))
                .build();
        final Cursor cursor = mContentResolver.query(uri, PROJECTION, null, null, null);

        if (cursor == null) return Collections.emptyList();

        final List<ShortcutInfo> result = new ArrayList<>();

        try {
            int i = 0;
            while (i < MAX_SHORTCUTS && cursor.moveToNext()) {
                final ShortcutInfo shortcut = createShortcutFromRow(cursor);
                if (shortcut == null) {
                    continue;
                }
                result.add(shortcut);
                i++;
            }
        } finally {
            cursor.close();
        }
        return result;
    }


    @VisibleForTesting
    ShortcutInfo createShortcutFromRow(Cursor cursor) {
        final ShortcutInfo.Builder builder = builderForContactShortcut(cursor);
        if (builder == null) {
            return null;
        }
        addIconForContact(cursor, builder);
        return builder.build();
    }

    @VisibleForTesting
    ShortcutInfo.Builder builderForContactShortcut(Cursor cursor) {
        final long id = cursor.getLong(0);
        final String lookupKey = cursor.getString(1);
        final String displayName = cursor.getString(2);
        return builderForContactShortcut(id, lookupKey, displayName);
    }

    @VisibleForTesting
    ShortcutInfo.Builder builderForContactShortcut(long id, String lookupKey, String displayName) {
        if (lookupKey == null || displayName == null) {
            return null;
        }
        final PersistableBundle extras = new PersistableBundle();
        extras.putLong(Contacts._ID, id);
        extras.putInt(EXTRA_SHORTCUT_TYPE, SHORTCUT_TYPE_CONTACT_URI);

        final ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mContext, lookupKey)
                .setIntent(ImplicitIntentsUtil.getIntentForQuickContactLauncherShortcut(mContext,
                        Contacts.getLookupUri(id, lookupKey)))
                .setDisabledMessage(mContext.getString(R.string.dynamic_shortcut_disabled_message))
                .setExtras(extras);

        setLabel(builder, displayName);
        return builder;
    }

    @VisibleForTesting
    ShortcutInfo getActionShortcutInfo(String id, String label, Intent action, Icon icon) {
        if (id == null || label == null) {
            return null;
        }
        final PersistableBundle extras = new PersistableBundle();
        extras.putInt(EXTRA_SHORTCUT_TYPE, SHORTCUT_TYPE_ACTION_URI);

        final ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mContext, id)
                .setIntent(action)
                .setIcon(icon)
                .setExtras(extras)
                .setDisabledMessage(mContext.getString(R.string.dynamic_shortcut_disabled_message));

        setLabel(builder, label);
        return builder.build();
    }

    public ShortcutInfo getQuickContactShortcutInfo(long id, String lookupKey, String displayName) {
        final ShortcutInfo.Builder builder = builderForContactShortcut(id, lookupKey, displayName);
        if (builder == null) {
            return null;
        }
        addIconForContact(id, lookupKey, displayName, builder);
        return builder.build();
    }

    private void setLabel(ShortcutInfo.Builder builder, String label) {
        if (label.length() < mLongLabelMaxLength) {
            builder.setLongLabel(label);
        } else {
            builder.setLongLabel(label.substring(0, mLongLabelMaxLength - 1).trim() + "…");
        }

        if (label.length() < mShortLabelMaxLength) {
            builder.setShortLabel(label);
        } else {
            builder.setShortLabel(label.substring(0, mShortLabelMaxLength - 1).trim() + "…");
        }
    }

    private void addIconForContact(Cursor cursor, ShortcutInfo.Builder builder) {
        final long id = cursor.getLong(0);
        final String lookupKey = cursor.getString(1);
        final String displayName = cursor.getString(2);
        addIconForContact(id, lookupKey, displayName, builder);
    }

    private void addIconForContact(long id, String lookupKey, String displayName,
            ShortcutInfo.Builder builder) {
        Bitmap bitmap = getContactPhoto(id);
        if (bitmap == null) {
            bitmap = getFallbackAvatar(displayName, lookupKey);
        }
        final Icon icon;
        if (BuildCompat.isAtLeastO()) {
            icon = Icon.createWithAdaptiveBitmap(bitmap);
        } else {
            icon = Icon.createWithBitmap(bitmap);
        }

        builder.setIcon(icon);
    }

    private Bitmap getContactPhoto(long id) {
        final InputStream photoStream = Contacts.openContactPhotoInputStream(
                mContext.getContentResolver(),
                ContentUris.withAppendedId(Contacts.CONTENT_URI, id), true);

        if (photoStream == null) return null;
        try {
            final Bitmap bitmap = decodeStreamForShortcut(photoStream);
            photoStream.close();
            return bitmap;
        } catch (IOException e) {
            Log.e(TAG, "Failed to decode contact photo for shortcut. ID=" + id, e);
            return null;
        } finally {
            try {
                photoStream.close();
            } catch (IOException e) {
                // swallow
            }
        }
    }

    private Bitmap decodeStreamForShortcut(InputStream stream) throws IOException {
        final BitmapRegionDecoder bitmapDecoder = BitmapRegionDecoder.newInstance(stream, false);

        final int sourceWidth = bitmapDecoder.getWidth();
        final int sourceHeight = bitmapDecoder.getHeight();

        final int iconMaxWidth = mShortcutManager.getIconMaxWidth();
        final int iconMaxHeight = mShortcutManager.getIconMaxHeight();

        final int sampleSize = Math.min(
                BitmapUtil.findOptimalSampleSize(sourceWidth, mIconSize),
                BitmapUtil.findOptimalSampleSize(sourceHeight, mIconSize));
        final BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inSampleSize = sampleSize;

        final int scaledWidth = sourceWidth / opts.inSampleSize;
        final int scaledHeight = sourceHeight / opts.inSampleSize;

        final int targetWidth = Math.min(scaledWidth, iconMaxWidth);
        final int targetHeight = Math.min(scaledHeight, iconMaxHeight);

        // Make it square.
        final int targetSize = Math.min(targetWidth, targetHeight);

        // The region is defined in the coordinates of the source image then the sampling is
        // done on the extracted region.
        final int prescaledXOffset = ((scaledWidth - targetSize) * opts.inSampleSize) / 2;
        final int prescaledYOffset = ((scaledHeight - targetSize) * opts.inSampleSize) / 2;

        final Bitmap bitmap = bitmapDecoder.decodeRegion(new Rect(
                prescaledXOffset, prescaledYOffset,
                sourceWidth - prescaledXOffset, sourceHeight - prescaledYOffset
        ), opts);
        bitmapDecoder.recycle();

        if (!BuildCompat.isAtLeastO()) {
            return BitmapUtil.getRoundedBitmap(bitmap, targetSize, targetSize);
        }

        return bitmap;
    }

    private Bitmap getFallbackAvatar(String displayName, String lookupKey) {
        // Use a circular icon if we're not on O or higher.
        final boolean circularIcon = !BuildCompat.isAtLeastO();

        final ContactPhotoManager.DefaultImageRequest request =
                new ContactPhotoManager.DefaultImageRequest(displayName, lookupKey, circularIcon);
        if (BuildCompat.isAtLeastO()) {
            // On O, scale the image down to add the padding needed by AdaptiveIcons.
            request.scale = LetterTileDrawable.getAdaptiveIconScale();
        }
        final Drawable avatar = ContactPhotoManager.getDefaultAvatarDrawableForContact(
                mContext.getResources(), true, request);
        final Bitmap result = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
        // The avatar won't draw unless it thinks it is visible
        avatar.setVisible(true, true);
        final Canvas canvas = new Canvas(result);
        avatar.setBounds(0, 0, mIconSize, mIconSize);
        avatar.draw(canvas);
        return result;
    }

    @VisibleForTesting
    void handleFlagDisabled() {
        removeAllShortcuts();
        mJobScheduler.cancel(ContactsJobService.DYNAMIC_SHORTCUTS_JOB_ID);
    }

    private void removeAllShortcuts() {
        mShortcutManager.removeAllDynamicShortcuts();

        final List<ShortcutInfo> pinned = mShortcutManager.getPinnedShortcuts();
        final List<String> ids = new ArrayList<>(pinned.size());
        for (ShortcutInfo shortcut : pinned) {
            ids.add(shortcut.getId());
        }
        mShortcutManager.disableShortcuts(ids, mContext
                .getString(R.string.dynamic_shortcut_disabled_message));
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "DynamicShortcuts have been removed.");
        }
    }

    @VisibleForTesting
    void scheduleUpdateJob() {
        final JobInfo job = new JobInfo.Builder(
                ContactsJobService.DYNAMIC_SHORTCUTS_JOB_ID,
                new ComponentName(mContext, ContactsJobService.class))
                // We just observe all changes to contacts. It would be better to be more granular
                // but CP2 only notifies using this URI anyway so there isn't any point in adding
                // that complexity.
                .addTriggerContentUri(new JobInfo.TriggerContentUri(ContactsContract.AUTHORITY_URI,
                        JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
                .setTriggerContentUpdateDelay(mContentChangeMinUpdateDelay)
                .setTriggerContentMaxDelay(mContentChangeMaxUpdateDelay)
                .build();
        mJobScheduler.schedule(job);
    }

    void updateInBackground() {
        new ShortcutUpdateTask(this).execute();
    }

    public synchronized static void initialize(Context context) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            final Flags flags = Flags.getInstance();
            Log.d(TAG, "DyanmicShortcuts.initialize\nVERSION >= N_MR1? " +
                    (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) +
                    "\nisJobScheduled? " +
                    (CompatUtils.isLauncherShortcutCompatible() && isJobScheduled(context)) +
                    "\nminDelay=" +
                    flags.getInteger(Experiments.DYNAMIC_MIN_CONTENT_CHANGE_UPDATE_DELAY_MILLIS) +
                    "\nmaxDelay=" +
                    flags.getInteger(Experiments.DYNAMIC_MAX_CONTENT_CHANGE_UPDATE_DELAY_MILLIS));
        }

        if (!CompatUtils.isLauncherShortcutCompatible()) return;

        final DynamicShortcuts shortcuts = new DynamicShortcuts(context);

        if (!shortcuts.hasRequiredPermissions()) {
            final IntentFilter filter = new IntentFilter();
            filter.addAction(RequestPermissionsActivity.BROADCAST_PERMISSIONS_GRANTED);
            LocalBroadcastManager.getInstance(shortcuts.mContext).registerReceiver(
                    new PermissionsGrantedReceiver(), filter);
        } else if (!isJobScheduled(context)) {
            // Update the shortcuts. If the job is already scheduled then either the app is being
            // launched to run the job in which case the shortcuts will get updated when it runs or
            // it has been launched for some other reason and the data we care about for shortcuts
            // hasn't changed. Because the job reschedules itself after completion this check
            // essentially means that this will run on each app launch that happens after a reboot.
            // Note: the task schedules the job after completing.
            new ShortcutUpdateTask(shortcuts).execute();
        }
    }

    @VisibleForTesting
    public static void reset(Context context) {
        final JobScheduler jobScheduler =
                (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
        jobScheduler.cancel(ContactsJobService.DYNAMIC_SHORTCUTS_JOB_ID);

        if (!CompatUtils.isLauncherShortcutCompatible()) {
            return;
        }
        new DynamicShortcuts(context).removeAllShortcuts();
    }

    @VisibleForTesting
    boolean hasRequiredPermissions() {
        return PermissionsUtil.hasContactsPermissions(mContext);
    }

    public static void updateFromJob(final JobService service, final JobParameters jobParams) {
        new ShortcutUpdateTask(new DynamicShortcuts(service)) {
            @Override
            protected void onPostExecute(Void aVoid) {
                // Must call super first which will reschedule the job before we call jobFinished
                super.onPostExecute(aVoid);
                service.jobFinished(jobParams, false);
            }
        }.execute();
    }

    @VisibleForTesting
    public static boolean isJobScheduled(Context context) {
        final JobScheduler scheduler = (JobScheduler) context
                .getSystemService(Context.JOB_SCHEDULER_SERVICE);
        return scheduler.getPendingJob(ContactsJobService.DYNAMIC_SHORTCUTS_JOB_ID) != null;
    }

    public static void reportShortcutUsed(Context context, String lookupKey) {
        if (!CompatUtils.isLauncherShortcutCompatible() || lookupKey == null) return;
        final ShortcutManager shortcutManager = (ShortcutManager) context
                .getSystemService(Context.SHORTCUT_SERVICE);
        shortcutManager.reportShortcutUsed(lookupKey);
    }

    private static class ShortcutUpdateTask extends AsyncTask<Void, Void, Void> {
        private DynamicShortcuts mDynamicShortcuts;

        public ShortcutUpdateTask(DynamicShortcuts shortcuts) {
            mDynamicShortcuts = shortcuts;
        }

        @Override
        protected Void doInBackground(Void... voids) {
            mDynamicShortcuts.refresh();
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "ShorcutUpdateTask.onPostExecute");
            }
            // The shortcuts may have changed so update the job so that we are observing the
            // correct Uris
            mDynamicShortcuts.scheduleUpdateJob();
        }
    }

    private static class PermissionsGrantedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Clear the receiver.
            LocalBroadcastManager.getInstance(context).unregisterReceiver(this);
            DynamicShortcuts.initialize(context);
        }
    }
}
