/*
 * 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 static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_UNKNOWN;

import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.util.SparseIntArray;
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
import java.util.List;

/**
 * Action that check each device's power status.
 */
public class PowerStatusMonitorAction extends HdmiCecFeatureAction {
    private static final String TAG = "PowerStatusMonitorAction";

    // State that waits for <Report Power Status> once sending <Give Device Power Status>
    // to all external devices.
    private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1;
    // State that waits for next monitoring
    private static final int STATE_WAIT_FOR_NEXT_MONITORING = 2;

    private static final int INVALID_POWER_STATUS = POWER_STATUS_UNKNOWN - 1;

    // Monitoring interval (60s)
    private static final int MONITORING_INTERNAL_MS = 60000;

    // Timeout once sending <Give Device Power Status>
    private static final int REPORT_POWER_STATUS_TIMEOUT_MS = 5000;

    // Container for current power status of all external devices.
    // The key is a logical address a device and the value is current power status of it
    // Whenever the action receives <Report Power Status> from a device,
    // it removes an entry of the given device.
    // If this is non-empty when timeout for STATE_WAIT_FOR_REPORT_POWER_STATUS happens,
    // updates power status of all remaining devices into POWER_STATUS_UNKNOWN.
    private final SparseIntArray mPowerStatus = new SparseIntArray();

    PowerStatusMonitorAction(HdmiCecLocalDevice source) {
        super(source);
    }

    @Override
    boolean start() {
        queryPowerStatus();
        return true;
    }

    @Override
    boolean processCommand(HdmiCecMessage cmd) {
        if (mState == STATE_WAIT_FOR_REPORT_POWER_STATUS
                && cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS) {
            return handleReportPowerStatus(cmd);
        }
        return false;
    }

    private boolean handleReportPowerStatus(HdmiCecMessage cmd) {
        int sourceAddress = cmd.getSource();
        int oldStatus = mPowerStatus.get(sourceAddress, INVALID_POWER_STATUS);
        if (oldStatus == INVALID_POWER_STATUS) {
            // if no device exists for incoming message, hands it over to other actions.
            return false;
        }
        int newStatus = cmd.getParams()[0] & 0xFF;
        updatePowerStatus(sourceAddress, newStatus, true);
        return true;
    }

    @Override
    void handleTimerEvent(int state) {
        switch (mState) {
            case STATE_WAIT_FOR_NEXT_MONITORING:
                queryPowerStatus();
                break;
            case STATE_WAIT_FOR_REPORT_POWER_STATUS:
                handleTimeout();
                break;
        }
    }

    private void handleTimeout() {
        for (int i = 0; i < mPowerStatus.size(); ++i) {
            int logicalAddress = mPowerStatus.keyAt(i);
            updatePowerStatus(logicalAddress, POWER_STATUS_UNKNOWN, false);
        }
        mPowerStatus.clear();
        mState = STATE_WAIT_FOR_NEXT_MONITORING;
    }

    private void resetPowerStatus(List<HdmiDeviceInfo> deviceInfos) {
        mPowerStatus.clear();
        for (HdmiDeviceInfo info : deviceInfos) {
            mPowerStatus.append(info.getLogicalAddress(), info.getDevicePowerStatus());
        }
    }

    private void queryPowerStatus() {
        List<HdmiDeviceInfo> deviceInfos = tv().getDeviceInfoList(false);
        resetPowerStatus(deviceInfos);
        for (HdmiDeviceInfo info : deviceInfos) {
            final int logicalAddress = info.getLogicalAddress();
            sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
                    logicalAddress),
                    new SendMessageCallback() {
                        @Override
                        public void onSendCompleted(int error) {
                            // If fails to send <Give Device Power Status>,
                            // update power status into UNKNOWN.
                            if (error != SendMessageResult.SUCCESS) {
                               updatePowerStatus(logicalAddress, POWER_STATUS_UNKNOWN, true);
                            }
                        }
                    });
        }

        mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;

        // Add both timers, monitoring and timeout.
        addTimer(STATE_WAIT_FOR_NEXT_MONITORING, MONITORING_INTERNAL_MS);
        addTimer(STATE_WAIT_FOR_REPORT_POWER_STATUS, REPORT_POWER_STATUS_TIMEOUT_MS);
    }

    private void updatePowerStatus(int logicalAddress, int newStatus, boolean remove) {
        tv().updateDevicePowerStatus(logicalAddress, newStatus);

        if (remove) {
            mPowerStatus.delete(logicalAddress);
        }
    }
}
