/*
 * 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.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Pair;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.hdmi.HdmiControlService.DevicePollingCallback;

import java.util.ArrayList;
import java.util.List;

/**
 * Encapsulates a sequence of CEC command exchange for a certain feature.
 * <p>
 * Many CEC features are accomplished by CEC devices on the bus exchanging more than one
 * command. {@link HdmiCecFeatureAction} represents the life cycle of the communication, manages the
 * state as the process progresses, and if necessary, returns the result to the caller which
 * initiates the action, through the callback given at the creation of the object. All the actual
 * action classes inherit FeatureAction.
 * <p>
 * More than one FeatureAction objects can be up and running simultaneously, maintained by
 * {@link HdmiCecLocalDevice}. Each action is passed a new command arriving from the bus, and either
 * consumes it if the command is what the action expects, or yields it to other action. Declared as
 * package private, accessed by {@link HdmiControlService} only.
 */
abstract class HdmiCecFeatureAction {
    private static final String TAG = "HdmiCecFeatureAction";

    // Timer handler message used for timeout event
    protected static final int MSG_TIMEOUT = 100;

    // Default state used in common by all the feature actions.
    protected static final int STATE_NONE = 0;

    // Internal state indicating the progress of action.
    protected int mState = STATE_NONE;

    private final HdmiControlService mService;
    private final HdmiCecLocalDevice mSource;

    // Timer that manages timeout events.
    protected ActionTimer mActionTimer;

    private ArrayList<Pair<HdmiCecFeatureAction, Runnable>> mOnFinishedCallbacks;

    HdmiCecFeatureAction(HdmiCecLocalDevice source) {
        mSource = source;
        mService = mSource.getService();
        mActionTimer = createActionTimer(mService.getServiceLooper());
    }

    @VisibleForTesting
    void setActionTimer(ActionTimer actionTimer) {
        mActionTimer = actionTimer;
    }

    /**
     * Called right after the action is created. Initialization or first step to take
     * for the action can be done in this method.
     *
     * @return true if the operation is successful; otherwise false.
     */
    abstract boolean start();

    /**
     * Process the command. Called whenever a new command arrives.
     *
     * @param cmd command to process
     * @return true if the command was consumed in the process; Otherwise false, which
     *          indicates that the command shall be handled by other actions.
     */
    abstract boolean processCommand(HdmiCecMessage cmd);

    /**
     * Called when the action should handle the timer event it created before.
     *
     * <p>CEC standard mandates each command transmission should be responded within
     * certain period of time. The method is called when the timer it created as it transmitted
     * a command gets expired. Inner logic should take an appropriate action.
     *
     * @param state the state associated with the time when the timer was created
     */
    abstract void handleTimerEvent(int state);

    /**
     * Timer handler interface used for FeatureAction classes.
     */
    interface ActionTimer {
        /**
         * Send a timer message.
         *
         * Also carries the state of the action when the timer is created. Later this state is
         * compared to the one the action is in when it receives the timer to let the action tell
         * the right timer to handle.
         *
         * @param state state of the action is in
         * @param delayMillis amount of delay for the timer
         */
        void sendTimerMessage(int state, long delayMillis);

        /**
         * Removes any pending timer message.
         */
        void clearTimerMessage();
    }

    private class ActionTimerHandler extends Handler implements ActionTimer {

        public ActionTimerHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void sendTimerMessage(int state, long delayMillis) {
            // The third argument(0) is not used.
            sendMessageDelayed(obtainMessage(MSG_TIMEOUT, state, 0), delayMillis);
        }

        @Override
        public void clearTimerMessage() {
            removeMessages(MSG_TIMEOUT);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_TIMEOUT:
                handleTimerEvent(msg.arg1);
                break;
            default:
                Slog.w(TAG, "Unsupported message:" + msg.what);
                break;
            }
        }
    }

    private ActionTimer createActionTimer(Looper looper) {
        return new ActionTimerHandler(looper);
    }

    // Add a new timer. The timer event will come to mActionTimer.handleMessage() in
    // delayMillis.
    protected void addTimer(int state, int delayMillis) {
        mActionTimer.sendTimerMessage(state, delayMillis);
    }

    protected final void sendCommand(HdmiCecMessage cmd) {
        mService.sendCecCommand(cmd);
    }

    protected final void sendCommand(HdmiCecMessage cmd,
            HdmiControlService.SendMessageCallback callback) {
        mService.sendCecCommand(cmd, callback);
    }

    protected final void addAndStartAction(HdmiCecFeatureAction action) {
        mSource.addAndStartAction(action);
    }

    protected final <T extends HdmiCecFeatureAction> List<T> getActions(final Class<T> clazz) {
        return mSource.getActions(clazz);
    }

    protected final HdmiCecMessageCache getCecMessageCache() {
        return mSource.getCecMessageCache();
    }

    /**
     * Remove the action from the action queue. This is called after the action finishes
     * its role.
     *
     * @param action
     */
    protected final void removeAction(HdmiCecFeatureAction action) {
        mSource.removeAction(action);
    }

    protected final <T extends HdmiCecFeatureAction> void removeAction(final Class<T> clazz) {
        mSource.removeActionExcept(clazz, null);
    }

    protected final <T extends HdmiCecFeatureAction> void removeActionExcept(final Class<T> clazz,
            final HdmiCecFeatureAction exception) {
        mSource.removeActionExcept(clazz, exception);
    }

    protected final void pollDevices(DevicePollingCallback callback, int pickStrategy,
            int retryCount) {
        mService.pollDevices(callback, getSourceAddress(), pickStrategy, retryCount);
    }

    /**
     * Clean up action's state.
     *
     * <p>Declared as package-private. Only {@link HdmiControlService} can access it.
     */
    void clear() {
        mState = STATE_NONE;
        // Clear all timers.
        mActionTimer.clearTimerMessage();
    }

    /**
     * Finish up the action. Reset the state, and remove itself from the action queue.
     */
    protected void finish() {
        finish(true);
    }

    void finish(boolean removeSelf) {
        clear();
        if (removeSelf) {
            removeAction(this);
        }
        if (mOnFinishedCallbacks != null) {
            for (Pair<HdmiCecFeatureAction, Runnable> actionCallbackPair: mOnFinishedCallbacks) {
                if (actionCallbackPair.first.mState != STATE_NONE) {
                    actionCallbackPair.second.run();
                }
            }
            mOnFinishedCallbacks = null;
        }
    }

    protected final HdmiCecLocalDevice localDevice() {
        return mSource;
    }

    protected final HdmiCecLocalDevicePlayback playback() {
        return (HdmiCecLocalDevicePlayback) mSource;
    }

    protected final HdmiCecLocalDeviceTv tv() {
        return (HdmiCecLocalDeviceTv) mSource;
    }

    protected final int getSourceAddress() {
        return mSource.getDeviceInfo().getLogicalAddress();
    }

    protected final int getSourcePath() {
        return mSource.getDeviceInfo().getPhysicalAddress();
    }

    protected final void sendUserControlPressedAndReleased(int targetAddress, int uiCommand) {
        mSource.sendUserControlPressedAndReleased(targetAddress, uiCommand);
    }

    protected final void addOnFinishedCallback(HdmiCecFeatureAction action, Runnable runnable) {
        if (mOnFinishedCallbacks == null) {
            mOnFinishedCallbacks = new ArrayList<>();
        }
        mOnFinishedCallbacks.add(Pair.create(action, runnable));
    }
}
