/*
 * 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.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.os.AsyncTask;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.util.TimingLogger;

import com.android.contacts.activities.PeopleActivity;
import com.android.contacts.database.SimContactDao;
import com.android.contacts.model.SimCard;
import com.android.contacts.model.SimContact;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contactsbind.FeedbackHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Imports {@link SimContact}s from a background thread
 */
public class SimImportService extends Service {

    private static final String TAG = "SimImportService";

    /**
     * Wrapper around the service state for testability
     */
    public interface StatusProvider {

        /**
         * Returns whether there is any imports still pending
         *
         * <p>This should be called from the UI thread</p>
         */
        boolean isRunning();

        /**
         * Returns whether an import for sim has been requested
         *
         * <p>This should be called from the UI thread</p>
         */
        boolean isImporting(SimCard sim);
    }

    public static final String EXTRA_ACCOUNT = "account";
    public static final String EXTRA_SIM_CONTACTS = "simContacts";
    public static final String EXTRA_SIM_SUBSCRIPTION_ID = "simSubscriptionId";
    public static final String EXTRA_RESULT_CODE = "resultCode";
    public static final String EXTRA_RESULT_COUNT = "count";
    public static final String EXTRA_OPERATION_REQUESTED_AT_TIME = "requestedTime";

    public static final String BROADCAST_SERVICE_STATE_CHANGED =
            SimImportService.class.getName() + "#serviceStateChanged";
    public static final String BROADCAST_SIM_IMPORT_COMPLETE =
            SimImportService.class.getName() + "#simImportComplete";

    public static final int RESULT_UNKNOWN = 0;
    public static final int RESULT_SUCCESS = 1;
    public static final int RESULT_FAILURE = 2;

    // VCardService uses jobIds for it's notifications which count up from 0 so we just use a
    // bigger number to prevent overlap.
    private static final int NOTIFICATION_ID = 100;

    private ExecutorService mExecutor = Executors.newSingleThreadExecutor();

    // Keeps track of current tasks. This is only modified from the UI thread.
    private static List<ImportTask> sPending = new ArrayList<>();

    private static StatusProvider sStatusProvider = new StatusProvider() {
        @Override
        public boolean isRunning() {
            return !sPending.isEmpty();
        }

        @Override
        public boolean isImporting(SimCard sim) {
            return SimImportService.isImporting(sim);
        }
    };

    /**
     * Returns whether an import for sim has been requested
     *
     * <p>This should be called from the UI thread</p>
     */
    private static boolean isImporting(SimCard sim) {
        for (ImportTask task : sPending) {
            if (task.getSim().equals(sim)) {
                return true;
            }
        }
        return false;
    }

    public static StatusProvider getStatusProvider() {
        return sStatusProvider;
    }

    /**
     * Starts an import of the contacts from the sim into the target account
     *
     * @param context context to use for starting the service
     * @param subscriptionId the subscriptionId of the SIM card that is being imported. See
     *                       {@link android.telephony.SubscriptionInfo#getSubscriptionId()}.
     *                       Upon completion the SIM for that subscription ID will be marked as
     *                       imported
     * @param contacts the contacts to import
     * @param targetAccount the account import the contacts into
     */
    public static void startImport(Context context, int subscriptionId,
            ArrayList<SimContact> contacts, AccountWithDataSet targetAccount) {
        context.startService(new Intent(context, SimImportService.class)
                .putExtra(EXTRA_SIM_CONTACTS, contacts)
                .putExtra(EXTRA_SIM_SUBSCRIPTION_ID, subscriptionId)
                .putExtra(EXTRA_ACCOUNT, targetAccount));
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, final int startId) {
        final ImportTask task = createTaskForIntent(intent, startId);
        if (task == null) {
            new StopTask(this, startId).executeOnExecutor(mExecutor);
            return START_NOT_STICKY;
        }
        sPending.add(task);
        task.executeOnExecutor(mExecutor);
        notifyStateChanged();
        return START_REDELIVER_INTENT;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mExecutor.shutdown();
    }

    private ImportTask createTaskForIntent(Intent intent, int startId) {
        final AccountWithDataSet targetAccount = intent.getParcelableExtra(EXTRA_ACCOUNT);
        final ArrayList<SimContact> contacts =
                intent.getParcelableArrayListExtra(EXTRA_SIM_CONTACTS);

        final int subscriptionId = intent.getIntExtra(EXTRA_SIM_SUBSCRIPTION_ID,
                SimCard.NO_SUBSCRIPTION_ID);
        final SimContactDao dao = SimContactDao.create(this);
        final SimCard sim = dao.getSimBySubscriptionId(subscriptionId);
        if (sim != null) {
            return new ImportTask(sim, contacts, targetAccount, dao, startId);
        } else {
            return null;
        }
    }

    private Notification getCompletedNotification() {
        final Intent intent = new Intent(this, PeopleActivity.class);
        final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setOngoing(false)
                .setAutoCancel(true)
                .setContentTitle(this.getString(R.string.importing_sim_finished_title))
                .setColor(this.getResources().getColor(R.color.dialtacts_theme_color))
                .setSmallIcon(R.drawable.quantum_ic_done_vd_theme_24)
                .setContentIntent(PendingIntent.getActivity(this, 0, intent, 0));
        return builder.build();
    }

    private Notification getFailedNotification() {
        final Intent intent = new Intent(this, PeopleActivity.class);
        final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setOngoing(false)
                .setAutoCancel(true)
                .setContentTitle(this.getString(R.string.importing_sim_failed_title))
                .setContentText(this.getString(R.string.importing_sim_failed_message))
                .setColor(this.getResources().getColor(R.color.dialtacts_theme_color))
                .setSmallIcon(R.drawable.quantum_ic_error_vd_theme_24)
                .setContentIntent(PendingIntent.getActivity(this, 0, intent, 0));
        return builder.build();
    }

    private Notification getImportingNotification() {
        final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        final String description = getString(R.string.importing_sim_in_progress_title);
        builder.setOngoing(true)
                .setProgress(/* current */ 0, /* max */ 100, /* indeterminate */ true)
                .setContentTitle(description)
                .setColor(this.getResources().getColor(R.color.dialtacts_theme_color))
                .setSmallIcon(android.R.drawable.stat_sys_download);
        return builder.build();
    }

    private void notifyStateChanged() {
        LocalBroadcastManager.getInstance(this).sendBroadcast(
                new Intent(BROADCAST_SERVICE_STATE_CHANGED));
    }

    // Schedule a task that calls stopSelf when it completes. This is used to ensure that the
    // calls to stopSelf occur in the correct order (because this service uses a single thread
    // executor this won't run until all work that was requested before it has finished)
    private static class StopTask extends AsyncTask<Void, Void, Void> {
        private Service mHost;
        private final int mStartId;

        private StopTask(Service host, int startId) {
            mHost = host;
            mStartId = startId;
        }

        @Override
        protected Void doInBackground(Void... params) {
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            mHost.stopSelf(mStartId);
        }
    }

    private class ImportTask extends AsyncTask<Void, Void, Boolean> {
        private final SimCard mSim;
        private final List<SimContact> mContacts;
        private final AccountWithDataSet mTargetAccount;
        private final SimContactDao mDao;
        private final NotificationManager mNotificationManager;
        private final int mStartId;
        private final long mStartTime;

        public ImportTask(SimCard sim, List<SimContact> contacts, AccountWithDataSet targetAccount,
                SimContactDao dao, int startId) {
            mSim = sim;
            mContacts = contacts;
            mTargetAccount = targetAccount;
            mDao = dao;
            mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            mStartId = startId;
            mStartTime = System.currentTimeMillis();
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            startForeground(NOTIFICATION_ID, getImportingNotification());
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            final TimingLogger timer = new TimingLogger(TAG, "import");
            try {
                // Just import them all at once.
                // Experimented with using smaller batches (e.g. 25 and 50) so that percentage
                // progress could be displayed however this slowed down the import by over a factor
                // of 2. If the batch size is over a 100 then most cases will only require a single
                // batch so we don't even worry about displaying accurate progress
                mDao.importContacts(mContacts, mTargetAccount);
                mDao.persistSimState(mSim.withImportedState(true));
                timer.addSplit("done");
                timer.dumpToLog();
            } catch (RemoteException|OperationApplicationException e) {
                FeedbackHelper.sendFeedback(SimImportService.this, TAG,
                        "Failed to import contacts from SIM card", e);
                return false;
            }
            return true;
        }

        public SimCard getSim() {
            return mSim;
        }

        @Override
        protected void onPostExecute(Boolean success) {
            super.onPostExecute(success);
            stopSelf(mStartId);

            Intent result;
            final Notification notification;
            if (success) {
                result = new Intent(BROADCAST_SIM_IMPORT_COMPLETE)
                        .putExtra(EXTRA_RESULT_CODE, RESULT_SUCCESS)
                        .putExtra(EXTRA_RESULT_COUNT, mContacts.size())
                        .putExtra(EXTRA_OPERATION_REQUESTED_AT_TIME, mStartTime)
                        .putExtra(EXTRA_SIM_SUBSCRIPTION_ID, mSim.getSubscriptionId());

                notification = getCompletedNotification();
            } else {
                result = new Intent(BROADCAST_SIM_IMPORT_COMPLETE)
                        .putExtra(EXTRA_RESULT_CODE, RESULT_FAILURE)
                        .putExtra(EXTRA_OPERATION_REQUESTED_AT_TIME, mStartTime)
                        .putExtra(EXTRA_SIM_SUBSCRIPTION_ID, mSim.getSubscriptionId());

                notification = getFailedNotification();
            }
            LocalBroadcastManager.getInstance(SimImportService.this).sendBroadcast(result);

            sPending.remove(this);

            // Only notify of completion if all the import requests have finished. We're using
            // the same notification for imports so in the rare case that a user has started
            // multiple imports the notification won't go away until all of them complete.
            if (sPending.isEmpty()) {
                stopForeground(false);
                mNotificationManager.notify(NOTIFICATION_ID, notification);
            }
            notifyStateChanged();
        }
    }
}
