/*
 * Copyright (C) 2020 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.settings.media;

import static android.app.slice.Slice.EXTRA_RANGE_VALUE;
import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;

import static com.android.settings.slices.CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import android.net.Uri;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.Log;

import androidx.annotation.VisibleForTesting;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.ListBuilder.InputRangeBuilder;
import androidx.slice.builders.SliceAction;

import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.notification.SoundSettings;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.media.MediaOutputSliceConstants;

import java.util.List;

/**
 * Display the Remote Media device information.
 */
public class RemoteMediaSlice implements CustomSliceable {

    private static final String TAG = "RemoteMediaSlice";
    private static final String MEDIA_ID = "media_id";
    private static final String ACTION_LAUNCH_DIALOG = "action_launch_dialog";
    private static final String SESSION_INFO = "RoutingSessionInfo";
    private static final String CUSTOMIZED_ACTION = "customized_action";

    private final Context mContext;

    private MediaDeviceUpdateWorker mWorker;

    @VisibleForTesting
    MediaRouter2Manager mRouterManager;

    public RemoteMediaSlice(Context context) {
        mContext = context;
    }

    @Override
    public void onNotifyChange(Intent intent) {
        final int newPosition = intent.getIntExtra(EXTRA_RANGE_VALUE, -1);
        final String id = intent.getStringExtra(MEDIA_ID);
        if (!TextUtils.isEmpty(id)) {
            getWorker().adjustSessionVolume(id, newPosition);
            return;
        }
        if (TextUtils.equals(ACTION_LAUNCH_DIALOG, intent.getStringExtra(CUSTOMIZED_ACTION))) {
            // Launch Media Output Dialog
            final RoutingSessionInfo info = intent.getParcelableExtra(SESSION_INFO);
            mContext.sendBroadcast(new Intent()
                    .setPackage(MediaOutputSliceConstants.SYSTEMUI_PACKAGE_NAME)
                    .setAction(MediaOutputSliceConstants.ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG)
                    .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
                            info.getClientPackageName()));
            // Dismiss volume panel
            mContext.sendBroadcast(new Intent()
                    .setPackage(MediaOutputSliceConstants.SETTINGS_PACKAGE_NAME)
                    .setAction(MediaOutputSliceConstants.ACTION_CLOSE_PANEL));
        }
    }

    @Override
    public Slice getSlice() {
        final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
                .setAccentColor(COLOR_NOT_TINTED);
        if (getWorker() == null) {
            Log.e(TAG, "Unable to get the slice worker.");
            return listBuilder.build();
        }
        if (mRouterManager == null) {
            mRouterManager = MediaRouter2Manager.getInstance(mContext);
        }
        // Only displaying remote devices
        final List<RoutingSessionInfo> infos = getWorker().getActiveRemoteMediaDevice();
        if (infos.isEmpty()) {
            Log.d(TAG, "No active remote media device");
            return listBuilder.build();
        }
        final CharSequence castVolume = mContext.getText(R.string.remote_media_volume_option_title);
        final IconCompat icon = IconCompat.createWithResource(mContext,
                R.drawable.ic_volume_remote);
        // To create an empty icon to indent the row
        final IconCompat emptyIcon = createEmptyIcon();
        for (RoutingSessionInfo info : infos) {
            final int maxVolume = info.getVolumeMax();
            if (maxVolume <= 0) {
                Log.d(TAG, "Unable to add Slice. " + info.getName() + ": max volume is "
                        + maxVolume);
                continue;
            }
            final CharSequence appName = Utils.getApplicationLabel(
                    mContext, info.getClientPackageName());
            final CharSequence outputTitle = mContext.getString(R.string.media_output_label_title,
                    appName);
            listBuilder.addInputRange(new InputRangeBuilder()
                    .setTitleItem(icon, ListBuilder.ICON_IMAGE)
                    .setTitle(castVolume)
                    .setInputAction(getSliderInputAction(info.getId().hashCode(), info.getId()))
                    .setPrimaryAction(getSoundSettingAction(castVolume, icon, info.getId()))
                    .setMax(maxVolume)
                    .setValue(info.getVolume()));

            final boolean isMediaOutputDisabled =
                    Utils.isMediaOutputDisabled(mRouterManager, info.getClientPackageName());
            final SpannableString spannableTitle = new SpannableString(
                    TextUtils.isEmpty(appName) ? "" : appName);
            spannableTitle.setSpan(new ForegroundColorSpan(
                            Utils.getColorAttrDefaultColor(
                                    mContext, android.R.attr.textColorSecondary)), 0,
                    spannableTitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
            listBuilder.addRow(new ListBuilder.RowBuilder()
                    .setTitle(isMediaOutputDisabled ? spannableTitle : outputTitle)
                    .setSubtitle(info.getName())
                    .setTitleItem(emptyIcon, ListBuilder.ICON_IMAGE)
                    .setPrimaryAction(getMediaOutputDialogAction(info, isMediaOutputDisabled)));
        }
        return listBuilder.build();
    }

    private IconCompat createEmptyIcon() {
        final Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
        return IconCompat.createWithBitmap(bitmap);
    }

    private PendingIntent getSliderInputAction(int requestCode, String id) {
        final Intent intent = new Intent(getUri().toString())
                .setData(getUri())
                .putExtra(MEDIA_ID, id)
                .setClass(mContext, SliceBroadcastReceiver.class);
        return PendingIntent.getBroadcast(mContext, requestCode, intent, 0);
    }

    private SliceAction getSoundSettingAction(CharSequence actionTitle, IconCompat icon,
            String id) {
        final Uri contentUri = new Uri.Builder().appendPath(id).build();
        final Intent intent = SliceBuilderUtils.buildSearchResultPageIntent(mContext,
                SoundSettings.class.getName(),
                id,
                mContext.getText(R.string.sound_settings).toString(), 0);
        intent.setClassName(mContext.getPackageName(), SubSettings.class.getName());
        intent.setData(contentUri);
        final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent,
                PendingIntent.FLAG_IMMUTABLE);
        final SliceAction primarySliceAction = SliceAction.createDeeplink(pendingIntent, icon,
                ListBuilder.ICON_IMAGE, actionTitle);
        return primarySliceAction;
    }

    private SliceAction getMediaOutputDialogAction(RoutingSessionInfo info,
            boolean isMediaOutputDisabled) {
        final Intent intent = new Intent(getUri().toString())
                .setData(getUri())
                .setClass(mContext, SliceBroadcastReceiver.class)
                .putExtra(CUSTOMIZED_ACTION, isMediaOutputDisabled ? "" : ACTION_LAUNCH_DIALOG)
                .putExtra(SESSION_INFO, info)
                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        final PendingIntent primaryBroadcastIntent = PendingIntent.getBroadcast(mContext,
                info.hashCode(), intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        final SliceAction primarySliceAction = SliceAction.createDeeplink(
                primaryBroadcastIntent,
                IconCompat.createWithResource(mContext, R.drawable.ic_volume_remote),
                ListBuilder.ICON_IMAGE,
                mContext.getString(R.string.media_output_label_title,
                        Utils.getApplicationLabel(mContext, info.getClientPackageName())));
        return primarySliceAction;
    }

    @Override
    public Uri getUri() {
        return REMOTE_MEDIA_SLICE_URI;
    }

    @Override
    public Intent getIntent() {
        return null;
    }

    @Override
    public Class getBackgroundWorkerClass() {
        return MediaDeviceUpdateWorker.class;
    }

    private MediaDeviceUpdateWorker getWorker() {
        if (mWorker == null) {
            mWorker = SliceBackgroundWorker.getInstance(getUri());
        }
        return mWorker;
    }
}
