/*
 * Copyright (C) 2018 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 android.hardware.hdmi;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;

/**
 * HdmiAudioSystemClient represents HDMI-CEC logical device of type Audio System in the Android
 * system which acts as an audio system device such as sound bar.
 *
 * <p>HdmiAudioSystemClient provides methods that control, get information from TV/Display device
 * connected through HDMI bus.
 *
 * @hide
 */
public final class HdmiAudioSystemClient extends HdmiClient {
    private static final String TAG = "HdmiAudioSystemClient";

    private static final int REPORT_AUDIO_STATUS_INTERVAL_MS = 500;

    private final Handler mHandler;
    private boolean mCanSendAudioStatus = true;
    private boolean mPendingReportAudioStatus;

    private int mLastVolume;
    private int mLastMaxVolume;
    private boolean mLastIsMute;

    @VisibleForTesting(visibility = Visibility.PACKAGE)
    public HdmiAudioSystemClient(IHdmiControlService service) {
        this(service, null);
    }

    @VisibleForTesting(visibility = Visibility.PACKAGE)
    public HdmiAudioSystemClient(IHdmiControlService service, @Nullable Handler handler) {
        super(service);
        mHandler = handler == null ? new Handler(Looper.getMainLooper()) : handler;
    }

    /**
     * Callback interface used to get the set System Audio Mode result.
     *
     * @hide
     */
    // TODO(b/110094868): unhide and add @SystemApi for Q
    public interface SetSystemAudioModeCallback {
        /**
         * Called when the input was changed.
         *
         * @param result the result of the set System Audio Mode
         */
        void onComplete(int result);
    }

    /** @hide */
    // TODO(b/110094868): unhide and add @SystemApi for Q
    @Override
    public int getDeviceType() {
        return HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM;
    }

    /**
     * Sends a Report Audio Status HDMI CEC command to TV devices when necessary.
     *
     * According to HDMI CEC specification, an audio system can report its audio status when System
     * Audio Mode is on, so that the TV can display the audio status of external amplifier.
     *
     * @hide
     */
    public void sendReportAudioStatusCecCommand(boolean isMuteAdjust, int volume, int maxVolume,
            boolean isMute) {
        if (isMuteAdjust) {
            // always report audio status when it's muted/unmuted
            try {
                mService.reportAudioStatus(getDeviceType(), volume, maxVolume, isMute);
            } catch (RemoteException e) {
                // do nothing. Reporting audio status is optional.
            }
            return;
        }

        mLastVolume = volume;
        mLastMaxVolume = maxVolume;
        mLastIsMute = isMute;
        if (mCanSendAudioStatus) {
            try {
                mService.reportAudioStatus(getDeviceType(), volume, maxVolume, isMute);
                mCanSendAudioStatus = false;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (mPendingReportAudioStatus) {
                            // report audio status if there is any pending message
                            try {
                                mService.reportAudioStatus(getDeviceType(), mLastVolume,
                                        mLastMaxVolume, mLastIsMute);
                                mHandler.postDelayed(this, REPORT_AUDIO_STATUS_INTERVAL_MS);
                            }  catch (RemoteException e) {
                                mCanSendAudioStatus = true;
                            } finally {
                                mPendingReportAudioStatus = false;
                            }
                        } else {
                            mCanSendAudioStatus = true;
                        }
                    }
                }, REPORT_AUDIO_STATUS_INTERVAL_MS);
            } catch (RemoteException e) {
                // do nothing. Reporting audio status is optional.
            }
        } else {
            // if audio status cannot be sent, send it latter
            mPendingReportAudioStatus = true;
        }
    }

    /**
     * Set System Audio Mode on/off with audio system device.
     *
     * @param state true to set System Audio Mode on. False to set off.
     * @param callback callback offer the setting result.
     *
     * @hide
     */
    // TODO(b/110094868): unhide and add @SystemApi for Q
    public void setSystemAudioMode(boolean state, @NonNull SetSystemAudioModeCallback callback) {
        // TODO(amyjojo): implement this when needed.
    }

    /**
     * When device is switching to an audio only source, this method is called to broadcast
     * a setSystemAudioMode on message to the HDMI CEC system without querying Active Source or
     * TV supporting System Audio Control or not. This is to get volume control passthrough
     * from STB even if TV does not support it.
     *
     * @hide
     */
    // TODO(b/110094868): unhide and add @SystemApi for Q
    public void setSystemAudioModeOnForAudioOnlySource() {
        try {
            mService.setSystemAudioModeOnForAudioOnlySource();
        } catch (RemoteException e) {
            Log.d(TAG, "Failed to set System Audio Mode on for Audio Only source");
        }
    }
}
