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

import com.google.android.collect.Sets;

import android.app.IntentService;
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.pm.PackageManager;
import android.preference.PreferenceManager;

import java.io.File;

public class AtraceService extends IntentService {

    private static String INTENT_ACTION_START_TRACING = "com.android.traceur.START_TRACING";
    private static String INTENT_ACTION_STOP_TRACING = "com.android.traceur.STOP_TRACING";

    private static String INTENT_EXTRA_FILENAME = "filename";
    private static String INTENT_EXTRA_TAGS= "tags";
    private static String INTENT_EXTRA_BUFFER = "buffer";
    private static String INTENT_EXTRA_APPS = "apps";

    private static int TRACE_NOTIFICATION = 1;
    private static int SAVING_TRACE_NOTIFICATION = 2;

    public static void startTracing(final Context context,
            String tags, int bufferSizeKb, boolean apps) {
        Intent intent = new Intent(context, AtraceService.class);
        intent.setAction(INTENT_ACTION_START_TRACING);
        intent.putExtra(INTENT_EXTRA_TAGS, tags);
        intent.putExtra(INTENT_EXTRA_BUFFER, bufferSizeKb);
        intent.putExtra(INTENT_EXTRA_APPS, apps);
        context.startService(intent);
    }

    public static void stopTracing(final Context context) {
        Intent intent = new Intent(context, AtraceService.class);
        intent.setAction(INTENT_ACTION_STOP_TRACING);
        intent.putExtra(INTENT_EXTRA_FILENAME, AtraceUtils.getOutputFilename());
        context.startService(intent);
    }

    public AtraceService() {
        super("AtraceService");
        setIntentRedelivery(true);
    }

    @Override
    public void onHandleIntent(Intent intent) {
        if (intent.getAction().equals(INTENT_ACTION_START_TRACING)) {
            startTracingInternal(intent.getStringExtra(INTENT_EXTRA_TAGS),
                intent.getIntExtra(INTENT_EXTRA_BUFFER,
                    Integer.parseInt(getApplicationContext()
                        .getString(R.string.default_buffer_size))),
                intent.getBooleanExtra(INTENT_EXTRA_APPS, false));
        } else if (intent.getAction().equals(INTENT_ACTION_STOP_TRACING)) {
            stopTracingInternal(intent.getStringExtra(INTENT_EXTRA_FILENAME));
        }
    }

    private void startTracingInternal(String tags, int bufferSizeKb, boolean appTracing) {
        Context context = getApplicationContext();
        Intent stopIntent = new Intent(Receiver.STOP_ACTION,
            null, context, Receiver.class);

        String title = context.getString(R.string.trace_is_being_recorded);
        String msg = context.getString(R.string.tap_to_stop_tracing);

        Notification.Builder notification =
            new Notification.Builder(context, Receiver.NOTIFICATION_CHANNEL)
                .setSmallIcon(R.drawable.stat_sys_adb)
                .setContentTitle(title)
                .setTicker(title)
                .setContentText(msg)
                .setContentIntent(
                    PendingIntent.getBroadcast(context, 0, stopIntent, 0))
                .setOngoing(true)
                .setLocalOnly(true)
                .setColor(getColor(
                    com.android.internal.R.color.system_notification_accent_color));

        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
            notification.extend(new Notification.TvExtender());
        }

        startForeground(TRACE_NOTIFICATION, notification.build());

        if (AtraceUtils.atraceStart(tags, bufferSizeKb, appTracing)) {
            stopForeground(Service.STOP_FOREGROUND_DETACH);
        } else {
            // Starting the trace was unsuccessful, so ensure that tracing
            // is stopped and the preference is reset.
            AtraceUtils.atraceStop();
            PreferenceManager.getDefaultSharedPreferences(context)
                .edit().putBoolean(context.getString(R.string.pref_key_tracing_on),
                        false).apply();
            QsService.updateTile();
            stopForeground(Service.STOP_FOREGROUND_REMOVE);
        }
    }

    private void stopTracingInternal(String outputFilename) {
        Context context = getApplicationContext();
        NotificationManager notificationManager =
            getSystemService(NotificationManager.class);

        Notification.Builder notification =
            new Notification.Builder(this, Receiver.NOTIFICATION_CHANNEL)
                .setSmallIcon(R.drawable.stat_sys_adb)
                .setContentTitle(getString(R.string.saving_trace))
                .setTicker(getString(R.string.saving_trace))
                .setLocalOnly(true)
                .setProgress(1, 0, true)
                .setColor(getColor(
                    com.android.internal.R.color.system_notification_accent_color));

        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
            notification.extend(new Notification.TvExtender());
        }

        startForeground(SAVING_TRACE_NOTIFICATION, notification.build());

        notificationManager.cancel(TRACE_NOTIFICATION);

        File file = AtraceUtils.getOutputFile(outputFilename);

        if (AtraceUtils.atraceDump(file)) {
            FileSender.postNotification(getApplicationContext(), file);
        }

        stopForeground(Service.STOP_FOREGROUND_REMOVE);
    }
}
