/*
 * 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.car.radio;

import android.app.Service;
import android.content.Intent;
import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.hardware.radio.RadioManager.ProgramInfo;
import android.hardware.radio.RadioTuner;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v4.media.MediaBrowserCompat.MediaItem;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;

import androidx.media.MediaBrowserServiceCompat;

import com.android.car.broadcastradio.support.Program;
import com.android.car.broadcastradio.support.media.BrowseTree;
import com.android.car.broadcastradio.support.platform.ProgramSelectorExt;
import com.android.car.radio.audio.AudioStreamController;
import com.android.car.radio.audio.IPlaybackStateListener;
import com.android.car.radio.media.TunerSession;
import com.android.car.radio.platform.ImageMemoryCache;
import com.android.car.radio.platform.RadioManagerExt;
import com.android.car.radio.service.IRadioCallback;
import com.android.car.radio.service.IRadioManager;
import com.android.car.radio.storage.RadioStorage;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * A persistent {@link Service} that is responsible for opening and closing a {@link RadioTuner}.
 * All radio operations should be delegated to this class. To be notified of any changes in radio
 * metadata, register as a {@link android.hardware.radio.RadioTuner.Callback} on this Service.
 *
 * <p>Utilize the {@link RadioBinder} to perform radio operations.
 */
public class RadioService extends MediaBrowserServiceCompat implements IPlaybackStateListener {

    private static String TAG = "BcRadioApp.uisrv";

    public static String ACTION_UI_SERVICE = "com.android.car.radio.ACTION_UI_SERVICE";

    /**
     * The amount of time to wait before re-trying to open the {@link #mRadioTuner}.
     */
    private static final int RADIO_TUNER_REOPEN_DELAY_MS = 5000;

    private final Object mLock = new Object();

    private int mReOpenRadioTunerCount = 0;
    private final Handler mHandler = new Handler();

    private RadioStorage mRadioStorage;
    private final RadioStorage.PresetsChangeListener mPresetsListener = this::onPresetsChanged;

    private RadioTuner mRadioTuner;

    private boolean mRadioSuccessfullyInitialized;

    private ProgramInfo mCurrentProgram;

    private RadioManagerExt mRadioManager;
    private ImageMemoryCache mImageCache;

    private AudioStreamController mAudioStreamController;

    private BrowseTree mBrowseTree;
    private TunerSession mMediaSession;
    private ProgramList mProgramList;

    /**
     * Whether or not this {@link RadioService} currently has audio focus, meaning it is the
     * primary driver of media. Usually, interaction with the radio will be prefaced with an
     * explicit request for audio focus. However, this is not ideal when muting the radio, so this
     * state needs to be tracked.
     */
    private boolean mHasAudioFocus;

    /**
     * An internal {@link android.hardware.radio.RadioTuner.Callback} that will listen for
     * changes in radio metadata and pass these method calls through to
     * {@link #mRadioTunerCallbacks}.
     */
    private RadioTuner.Callback mInternalRadioTunerCallback = new InternalRadioCallback();
    private List<IRadioCallback> mRadioTunerCallbacks = new ArrayList<>();

    @Override
    public IBinder onBind(Intent intent) {
        if (ACTION_UI_SERVICE.equals(intent.getAction())) {
            return mBinder;
        }
        return super.onBind(intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onCreate()");
        }

        mRadioManager = new RadioManagerExt(this);
        mAudioStreamController = new AudioStreamController(this, mRadioManager);
        mRadioStorage = RadioStorage.getInstance(this);
        mImageCache = new ImageMemoryCache(mRadioManager, 1000);

        mBrowseTree = new BrowseTree(this, mImageCache);
        mMediaSession = new TunerSession(this, mBrowseTree, mBinder, mImageCache);
        setSessionToken(mMediaSession.getSessionToken());
        mAudioStreamController.addPlaybackStateListener(mMediaSession);
        mBrowseTree.setAmFmRegionConfig(mRadioManager.getAmFmRegionConfig());

        mRadioStorage.addPresetsChangeListener(mPresetsListener);
        onPresetsChanged();

        mAudioStreamController.addPlaybackStateListener(this);

        openRadioBandInternal(mRadioStorage.getStoredRadioBand());

        mRadioSuccessfullyInitialized = true;
    }

    @Override
    public void onDestroy() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDestroy()");
        }

        mRadioStorage.removePresetsChangeListener(mPresetsListener);
        mMediaSession.release();
        mRadioManager.getRadioTunerExt().close();
        close();

        super.onDestroy();
    }

    private void onPresetsChanged() {
        synchronized (mLock) {
            mBrowseTree.setFavorites(new HashSet<>(mRadioStorage.getPresets()));
            mMediaSession.notifyFavoritesChanged();
        }
    }

    /**
     * Opens the current radio band. Currently, this only supports FM and AM bands.
     *
     * @param radioBand One of {@link RadioManager#BAND_FM}, {@link RadioManager#BAND_AM},
     *                  {@link RadioManager#BAND_FM_HD} or {@link RadioManager#BAND_AM_HD}.
     * @return {@link RadioManager#STATUS_OK} if successful; otherwise,
     * {@link RadioManager#STATUS_ERROR}.
     */
    private int openRadioBandInternal(int radioBand) {
        if (!mAudioStreamController.requestMuted(false)) return RadioManager.STATUS_ERROR;

        if (mRadioTuner == null) {
            mRadioTuner = mRadioManager.openSession(mInternalRadioTunerCallback, null);
            mProgramList = mRadioTuner.getDynamicProgramList(null);
            mBrowseTree.setProgramList(mProgramList);
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "openRadioBandInternal() STATUS_OK");
        }

        // Reset the counter for exponential backoff each time the radio tuner has been successfully
        // opened.
        mReOpenRadioTunerCount = 0;

        tuneToDefault(radioBand);

        return RadioManager.STATUS_OK;
    }

    private void tuneToDefault(int band) {
        if (!mAudioStreamController.preparePlayback(Optional.empty())) return;

        long storedChannel = mRadioStorage.getStoredRadioChannel(band);
        if (storedChannel != RadioStorage.INVALID_RADIO_CHANNEL) {
            Log.i(TAG, "Restoring stored program: " + storedChannel);
            mRadioTuner.tune(ProgramSelectorExt.createAmFmSelector(storedChannel));
        } else {
            Log.i(TAG, "No stored program, seeking forward to not play static");

            // TODO(b/80500464): don't hardcode, pull from tuner config
            long lastChannel;
            if (band == RadioManager.BAND_AM) lastChannel = 1620;
            else lastChannel = 108000;
            mRadioTuner.tune(ProgramSelectorExt.createAmFmSelector(lastChannel));

            mRadioTuner.scan(RadioTuner.DIRECTION_UP, true);
        }
    }

    /* TODO(b/73950974): remove onRadioMuteChanged from IRadioCallback,
     * use IPlaybackStateListener directly.
     */
    @Override
    public void onPlaybackStateChanged(@PlaybackStateCompat.State int state) {
        boolean muted = state != PlaybackStateCompat.STATE_PLAYING;
        synchronized (mLock) {
            for (IRadioCallback callback : mRadioTunerCallbacks) {
                try {
                    callback.onRadioMuteChanged(muted);
                } catch (RemoteException e) {
                    Log.e(TAG, "Mute state change callback failed", e);
                }
            }
        }
    }

    /**
     * Closes any active {@link RadioTuner}s and releases audio focus.
     */
    private void close() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "close()");
        }

        mAudioStreamController.requestMuted(true);

        if (mProgramList != null) {
            mProgramList.close();
            mProgramList = null;
        }
        if (mRadioTuner != null) {
            mRadioTuner.close();
            mRadioTuner = null;
        }
    }

    private IRadioManager.Stub mBinder = new IRadioManager.Stub() {
        /**
         * Tunes the radio to the given frequency. To be notified of a successful tune, register
         * as a {@link android.hardware.radio.RadioTuner.Callback}.
         */
        @Override
        public void tune(ProgramSelector sel) {
            if (!mAudioStreamController.preparePlayback(Optional.empty())) return;
            mRadioTuner.tune(sel);
        }

        @Override
        public List<ProgramInfo> getProgramList() {
            return mRadioTuner.getDynamicProgramList(null).toList();
        }

        /**
         * Seeks the radio forward. To be notified of a successful tune, register as a
         * {@link android.hardware.radio.RadioTuner.Callback}.
         */
        @Override
        public void seekForward() {
            if (!mAudioStreamController.preparePlayback(Optional.of(true))) return;

            if (mRadioTuner == null) {
                int radioStatus = openRadioBandInternal(mRadioStorage.getStoredRadioBand());
                if (radioStatus == RadioManager.STATUS_ERROR) {
                    return;
                }
            }

            mRadioTuner.scan(RadioTuner.DIRECTION_UP, true);
        }

        /**
         * Seeks the radio backwards. To be notified of a successful tune, register as a
         * {@link android.hardware.radio.RadioTuner.Callback}.
         */
        @Override
        public void seekBackward() {
            if (!mAudioStreamController.preparePlayback(Optional.of(false))) return;

            if (mRadioTuner == null) {
                int radioStatus = openRadioBandInternal(mRadioStorage.getStoredRadioBand());
                if (radioStatus == RadioManager.STATUS_ERROR) {
                    return;
                }
            }

            mRadioTuner.scan(RadioTuner.DIRECTION_DOWN, true);
        }

        /**
         * Mutes the radio.
         *
         * @return {@code true} if the mute was successful.
         */
        @Override
        public boolean mute() {
            return mAudioStreamController.requestMuted(true);
        }

        /**
         * Un-mutes the radio and causes audio to play.
         *
         * @return {@code true} if the un-mute was successful.
         */
        @Override
        public boolean unMute() {
            return mAudioStreamController.requestMuted(false);
        }

        /**
         * Returns {@code true} if the radio is currently muted.
         */
        @Override
        public boolean isMuted() {
            return mAudioStreamController.isMuted();
        }

        @Override
        public void addFavorite(Program program) {
            mRadioStorage.storePreset(program);
        }

        @Override
        public void removeFavorite(ProgramSelector sel) {
            mRadioStorage.removePreset(sel);
        }

        @Override
        public void switchBand(int radioBand) {
            tuneToDefault(radioBand);
        }

        /**
         * Adds the given {@link android.hardware.radio.RadioTuner.Callback} to be notified
         * of any radio metadata changes.
         */
        @Override
        public void addRadioTunerCallback(IRadioCallback callback) {
            if (callback == null) {
                return;
            }

            mRadioTunerCallbacks.add(callback);
        }

        /**
         * Removes the given {@link android.hardware.radio.RadioTuner.Callback} from receiving
         * any radio metadata chagnes.
         */
        @Override
        public void removeRadioTunerCallback(IRadioCallback callback) {
            if (callback == null) {
                return;
            }

            mRadioTunerCallbacks.remove(callback);
        }

        @Override
        public ProgramInfo getCurrentProgramInfo() {
            return mCurrentProgram;
        }

        /**
         * Returns {@code true} if the radio was able to successfully initialize. A value of
         * {@code false} here could mean that the {@code RadioService} was not able to connect to
         * the {@link RadioManager} or there were no radio modules on the current device.
         */
        @Override
        public boolean isInitialized() {
            return mRadioSuccessfullyInitialized;
        }

        /**
         * Returns {@code true} if the radio currently has focus and is therefore the application
         * that is supplying music.
         */
        @Override
        public boolean hasFocus() {
            return mHasAudioFocus;
        }
    };

    /**
     * A extension of {@link android.hardware.radio.RadioTuner.Callback} that delegates to a
     * callback registered on this service.
     */
    private class InternalRadioCallback extends RadioTuner.Callback {
        @Override
        public void onProgramInfoChanged(ProgramInfo info) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "Program info changed: " + info);
            }

            mCurrentProgram = Objects.requireNonNull(info);
            mMediaSession.notifyProgramInfoChanged(info);
            mAudioStreamController.notifyProgramInfoChanged();
            mRadioStorage.storeRadioChannel(info.getSelector());

            for (IRadioCallback callback : mRadioTunerCallbacks) {
                try {
                    callback.onCurrentProgramInfoChanged(info);
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to notify about changed radio station", e);
                }
            }
        }

        @Override
        public void onError(int status) {
            Log.e(TAG, "onError(); status: " + status);

            // If there is a hardware failure or the radio service died, then this requires a
            // re-opening of the radio tuner.
            if (status == RadioTuner.ERROR_HARDWARE_FAILURE
                    || status == RadioTuner.ERROR_SERVER_DIED) {
                close();

                // Attempt to re-open the RadioTuner. Each time the radio tuner fails to open, the
                // mReOpenRadioTunerCount will be incremented.
                mHandler.removeCallbacks(mOpenRadioTunerRunnable);
                mHandler.postDelayed(mOpenRadioTunerRunnable,
                        mReOpenRadioTunerCount * RADIO_TUNER_REOPEN_DELAY_MS);

                mReOpenRadioTunerCount++;
            }

            try {
                for (IRadioCallback callback : mRadioTunerCallbacks) {
                    callback.onError(status);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "onError(); Failed to notify IRadioCallbacks: " + e.getMessage());
            }
        }

        @Override
        public void onControlChanged(boolean control) {
            // If the radio loses control of the RadioTuner, then close it and allow it to be
            // re-opened when control has been gained.
            if (!control) {
                close();
                return;
            }

            if (mRadioTuner == null) {
                openRadioBandInternal(mRadioStorage.getStoredRadioBand());
            }
        }
    }

    private final Runnable mOpenRadioTunerRunnable =
            () -> openRadioBandInternal(mRadioStorage.getStoredRadioBand());

    @Override
    public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
        /* Radio application may restrict who can read its MediaBrowser tree.
         * Our implementation doesn't.
         */
        return mBrowseTree.getRoot();
    }

    @Override
    public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
        mBrowseTree.loadChildren(parentMediaId, result);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (BrowseTree.ACTION_PLAY_BROADCASTRADIO.equals(intent.getAction())) {
            Log.i(TAG, "Executing general play radio intent");
            mMediaSession.getController().getTransportControls().playFromMediaId(
                    mBrowseTree.getRoot().getRootId(), null);
            return START_NOT_STICKY;
        }

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder asBinder() {
        throw new UnsupportedOperationException("Not a binder");
    }
}
