/*
 * Copyright (C) 2014 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.server.hdmi;

import android.annotation.Nullable;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlCallback;
import android.os.RemoteException;
import android.util.Slog;

import java.util.List;

/**
 * Base feature action class for SystemAudioActionFromTv and SystemAudioActionFromAvr.
 */
abstract class SystemAudioAction extends HdmiCecFeatureAction {
    private static final String TAG = "SystemAudioAction";

    // Transient state to differentiate with STATE_NONE where the on-finished callback
    // will not be called.
    private static final int STATE_CHECK_ROUTING_IN_PRGRESS = 1;

    // State in which waits for <SetSystemAudioMode>.
    private static final int STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE = 2;

    private static final int MAX_SEND_RETRY_COUNT = 2;

    private static final int ON_TIMEOUT_MS = 5000;
    private static final int OFF_TIMEOUT_MS = HdmiConfig.TIMEOUT_MS;

    // Logical address of AV Receiver.
    protected final int mAvrLogicalAddress;

    // The target audio status of the action, whether to enable the system audio mode or not.
    protected boolean mTargetAudioStatus;

    @Nullable private final IHdmiControlCallback mCallback;

    private int mSendRetryCount = 0;

    /**
     * Constructor
     *
     * @param source {@link HdmiCecLocalDevice} instance
     * @param avrAddress logical address of AVR device
     * @param targetStatus Whether to enable the system audio mode or not
     * @param callback callback interface to be notified when it's done
     * @throw IllegalArugmentException if device type of sourceAddress and avrAddress is invalid
     */
    SystemAudioAction(HdmiCecLocalDevice source, int avrAddress, boolean targetStatus,
            IHdmiControlCallback callback) {
        super(source);
        HdmiUtils.verifyAddressType(avrAddress, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
        mAvrLogicalAddress = avrAddress;
        mTargetAudioStatus = targetStatus;
        mCallback = callback;
    }

    // Seq #27
    protected void sendSystemAudioModeRequest() {
        List<RoutingControlAction> routingActions = getActions(RoutingControlAction.class);
        if (!routingActions.isEmpty()) {
            mState = STATE_CHECK_ROUTING_IN_PRGRESS;
            // Should have only one Routing Control Action
            RoutingControlAction routingAction = routingActions.get(0);
            routingAction.addOnFinishedCallback(this, new Runnable() {
                @Override
                public void run() {
                    sendSystemAudioModeRequestInternal();
                }
            });
            return;
        }
        sendSystemAudioModeRequestInternal();
    }

    private void sendSystemAudioModeRequestInternal() {
        int avrPhysicalAddress = tv().getAvrDeviceInfo().getPhysicalAddress();
        HdmiCecMessage command = HdmiCecMessageBuilder.buildSystemAudioModeRequest(
                getSourceAddress(),
                mAvrLogicalAddress, avrPhysicalAddress, mTargetAudioStatus);
        sendCommand(command, new HdmiControlService.SendMessageCallback() {
            @Override
            public void onSendCompleted(int error) {
                if (error != Constants.SEND_RESULT_SUCCESS) {
                    HdmiLogger.debug("Failed to send <System Audio Mode Request>:" + error);
                    setSystemAudioMode(false);
                    finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
                }
            }
        });
        mState = STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE;
        addTimer(mState, mTargetAudioStatus ? ON_TIMEOUT_MS : OFF_TIMEOUT_MS);
    }

    private void handleSendSystemAudioModeRequestTimeout() {
        if (!mTargetAudioStatus  // Don't retry for Off case.
                || mSendRetryCount++ >= MAX_SEND_RETRY_COUNT) {
            HdmiLogger.debug("[T]:wait for <Set System Audio Mode>.");
            setSystemAudioMode(false);
            finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
            return;
        }
        sendSystemAudioModeRequest();
    }

    protected void setSystemAudioMode(boolean mode) {
        tv().setSystemAudioMode(mode, true);
    }

    @Override
    final boolean processCommand(HdmiCecMessage cmd) {
        switch (mState) {
            case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE:
                if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
                        && (cmd.getParams()[0] & 0xFF)
                                == Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST) {
                    HdmiLogger.debug("Failed to start system audio mode request.");
                    setSystemAudioMode(false);
                    finishWithCallback(HdmiControlManager.RESULT_EXCEPTION);
                    return true;
                }
                if (cmd.getOpcode() != Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE
                        || !HdmiUtils.checkCommandSource(cmd, mAvrLogicalAddress, TAG)) {
                    return false;
                }
                boolean receivedStatus = HdmiUtils.parseCommandParamSystemAudioStatus(cmd);
                if (receivedStatus == mTargetAudioStatus) {
                    setSystemAudioMode(receivedStatus);
                    startAudioStatusAction();
                    return true;
                } else {
                    HdmiLogger.debug("Unexpected system audio mode request:" + receivedStatus);
                    // Unexpected response, consider the request is newly initiated by AVR.
                    // To return 'false' will initiate new SystemAudioActionFromAvr by the control
                    // service.
                    finishWithCallback(HdmiControlManager.RESULT_EXCEPTION);
                    return false;
                }
            default:
                return false;
        }
    }

    protected void startAudioStatusAction() {
        addAndStartAction(new SystemAudioStatusAction(tv(), mAvrLogicalAddress, mCallback));
        finish();
    }

    protected void removeSystemAudioActionInProgress() {
        removeActionExcept(SystemAudioActionFromTv.class, this);
        removeActionExcept(SystemAudioActionFromAvr.class, this);
    }

    @Override
    final void handleTimerEvent(int state) {
        if (mState != state) {
            return;
        }
        switch (mState) {
            case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE:
                handleSendSystemAudioModeRequestTimeout();
                return;
        }
    }

    // TODO: if IHdmiControlCallback is general to other FeatureAction,
    //       move it into FeatureAction.
    protected void finishWithCallback(int returnCode) {
        if (mCallback != null) {
            try {
                mCallback.onComplete(returnCode);
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to invoke callback.", e);
            }
        }
        finish();
    }
}
