/*
 * Copyright (C) 2012 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.bluetooth.btservice;

import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.os.Message;
import android.os.UserManager;
import android.util.Log;

import com.android.internal.util.State;
import com.android.internal.util.StateMachine;

/**
 * This state machine handles Bluetooth Adapter State.
 * States:
 *      {@link OnState} : Bluetooth is on at this state
 *      {@link OffState}: Bluetooth is off at this state. This is the initial
 *      state.
 *      {@link PendingCommandState} : An enable / disable operation is pending.
 * TODO(BT): Add per process on state.
 */

final class AdapterState extends StateMachine {
    private static final boolean DBG = true;
    private static final boolean VDBG = true;
    private static final String TAG = "BluetoothAdapterState";

    static final int BLE_TURN_ON = 0;
    static final int USER_TURN_ON = 1;
    static final int BREDR_STARTED=2;
    static final int ENABLED_READY = 3;
    static final int BLE_STARTED=4;

    static final int USER_TURN_OFF = 20;
    static final int BEGIN_DISABLE = 21;
    static final int ALL_DEVICES_DISCONNECTED = 22;
    static final int BLE_TURN_OFF = 23;

    static final int DISABLED = 24;
    static final int BLE_STOPPED=25;
    static final int BREDR_STOPPED = 26;

    static final int BREDR_START_TIMEOUT = 100;
    static final int ENABLE_TIMEOUT = 101;
    static final int DISABLE_TIMEOUT = 103;
    static final int BLE_STOP_TIMEOUT = 104;
    static final int SET_SCAN_MODE_TIMEOUT = 105;
    static final int BLE_START_TIMEOUT = 106;
    static final int BREDR_STOP_TIMEOUT = 107;

    static final int USER_TURN_OFF_DELAY_MS=500;

    //TODO: tune me
    private static final int ENABLE_TIMEOUT_DELAY = 12000;
    private static final int DISABLE_TIMEOUT_DELAY = 8000;
    private static final int BREDR_START_TIMEOUT_DELAY = 4000;
    //BLE_START_TIMEOUT can happen quickly as it just a start gattservice
    private static final int BLE_START_TIMEOUT_DELAY = 2000; //To start GattService
    private static final int BLE_STOP_TIMEOUT_DELAY = 2000;
    //BREDR_STOP_TIMEOUT can < STOP_TIMEOUT
    private static final int BREDR_STOP_TIMEOUT_DELAY = 4000;
    private static final int PROPERTY_OP_DELAY =2000;
    private AdapterService mAdapterService;
    private AdapterProperties mAdapterProperties;
    private PendingCommandState mPendingCommandState = new PendingCommandState();
    private OnState mOnState = new OnState();
    private OffState mOffState = new OffState();
    private BleOnState mBleOnState = new BleOnState();

    public boolean isTurningOn() {
        boolean isTurningOn=  mPendingCommandState.isTurningOn();
        verboseLog("isTurningOn()=" + isTurningOn);
        return isTurningOn;
    }

    public boolean isBleTurningOn() {
        boolean isBleTurningOn=  mPendingCommandState.isBleTurningOn();
        verboseLog("isBleTurningOn()=" + isBleTurningOn);
        return isBleTurningOn;
    }

    public boolean isBleTurningOff() {
        boolean isBleTurningOff =  mPendingCommandState.isBleTurningOff();
        verboseLog("isBleTurningOff()=" + isBleTurningOff);
        return isBleTurningOff;
    }

    public boolean isTurningOff() {
        boolean isTurningOff= mPendingCommandState.isTurningOff();
        verboseLog("isTurningOff()=" + isTurningOff);
        return isTurningOff;
    }

    private AdapterState(AdapterService service, AdapterProperties adapterProperties) {
        super("BluetoothAdapterState:");
        addState(mOnState);
        addState(mBleOnState);
        addState(mOffState);
        addState(mPendingCommandState);
        mAdapterService = service;
        mAdapterProperties = adapterProperties;
        setInitialState(mOffState);
    }

    public static AdapterState make(AdapterService service, AdapterProperties adapterProperties) {
        Log.d(TAG, "make() - Creating AdapterState");
        AdapterState as = new AdapterState(service, adapterProperties);
        as.start();
        return as;
    }

    public void doQuit() {
        quitNow();
    }

    public void cleanup() {
        if(mAdapterProperties != null)
            mAdapterProperties = null;
        if(mAdapterService != null)
            mAdapterService = null;
    }

    private class OffState extends State {
        @Override
        public void enter() {
            infoLog("Entering OffState");
        }

        @Override
        public boolean processMessage(Message msg) {
            AdapterService adapterService = mAdapterService;
            if (adapterService == null) {
                errorLog("Received message in OffState after cleanup: " + msg.what);
                return false;
            }

            debugLog("Current state: OFF, message: " + msg.what);

            switch(msg.what) {
               case BLE_TURN_ON:
                   notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);
                   mPendingCommandState.setBleTurningOn(true);
                   transitionTo(mPendingCommandState);
                   sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
                   adapterService.BleOnProcessStart();
                   break;

               case USER_TURN_OFF:
                   //TODO: Handle case of service started and stopped without enable
                   break;

               default:
                   return false;
            }
            return true;
        }
    }

    private class BleOnState extends State {
        @Override
        public void enter() {
            infoLog("Entering BleOnState");
        }

        @Override
        public boolean processMessage(Message msg) {

            AdapterService adapterService = mAdapterService;
            AdapterProperties adapterProperties = mAdapterProperties;
            if ((adapterService == null) || (adapterProperties == null)) {
                errorLog("Received message in BleOnState after cleanup: " + msg.what);
                return false;
            }

            debugLog("Current state: BLE ON, message: " + msg.what);

            switch(msg.what) {
               case USER_TURN_ON:
                   notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON);
                   mPendingCommandState.setTurningOn(true);
                   transitionTo(mPendingCommandState);
                   sendMessageDelayed(BREDR_START_TIMEOUT, BREDR_START_TIMEOUT_DELAY);
                   adapterService.startCoreServices();
                   break;

               case USER_TURN_OFF:
                   notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_OFF);
                   mPendingCommandState.setBleTurningOff(true);
                   adapterProperties.onBleDisable();
                   transitionTo(mPendingCommandState);
                   sendMessageDelayed(DISABLE_TIMEOUT, DISABLE_TIMEOUT_DELAY);
                   boolean ret = adapterService.disableNative();
                   if (!ret) {
                        removeMessages(DISABLE_TIMEOUT);
                        errorLog("Error while calling disableNative");
                        //FIXME: what about post enable services
                        mPendingCommandState.setBleTurningOff(false);
                        notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
                   }
                   break;

               default:
                   return false;
            }
            return true;
        }
    }

    private class OnState extends State {
        @Override
        public void enter() {
            infoLog("Entering OnState");

            AdapterService adapterService = mAdapterService;
            if (adapterService == null) {
                errorLog("Entered OnState after cleanup");
                return;
            }
            adapterService.autoConnect();
        }

        @Override
        public boolean processMessage(Message msg) {
            AdapterProperties adapterProperties = mAdapterProperties;
            if (adapterProperties == null) {
                errorLog("Received message in OnState after cleanup: " + msg.what);
                return false;
            }

            debugLog("Current state: ON, message: " + msg.what);

            switch(msg.what) {
               case BLE_TURN_OFF:
                   notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_OFF);
                   mPendingCommandState.setTurningOff(true);
                   transitionTo(mPendingCommandState);

                   // Invoke onBluetoothDisable which shall trigger a
                   // setScanMode to SCAN_MODE_NONE
                   Message m = obtainMessage(SET_SCAN_MODE_TIMEOUT);
                   sendMessageDelayed(m, PROPERTY_OP_DELAY);
                   adapterProperties.onBluetoothDisable();
                   break;

               case USER_TURN_ON:
                   break;

               default:
                   return false;
            }
            return true;
        }
    }

    private class PendingCommandState extends State {
        private boolean mIsTurningOn;
        private boolean mIsTurningOff;
        private boolean mIsBleTurningOn;
        private boolean mIsBleTurningOff;

        public void enter() {
            infoLog("Entering PendingCommandState");
        }

        public void setTurningOn(boolean isTurningOn) {
            mIsTurningOn = isTurningOn;
        }

        public boolean isTurningOn() {
            return mIsTurningOn;
        }

        public void setTurningOff(boolean isTurningOff) {
            mIsTurningOff = isTurningOff;
        }

        public boolean isTurningOff() {
            return mIsTurningOff;
        }

        public void setBleTurningOn(boolean isBleTurningOn) {
            mIsBleTurningOn = isBleTurningOn;
        }

        public boolean isBleTurningOn() {
            return mIsBleTurningOn;
        }

        public void setBleTurningOff(boolean isBleTurningOff) {
            mIsBleTurningOff = isBleTurningOff;
        }

        public boolean isBleTurningOff() {
            return mIsBleTurningOff;
        }

        @Override
        public boolean processMessage(Message msg) {

            boolean isTurningOn= isTurningOn();
            boolean isTurningOff = isTurningOff();
            boolean isBleTurningOn = isBleTurningOn();
            boolean isBleTurningOff = isBleTurningOff();

            AdapterService adapterService = mAdapterService;
            AdapterProperties adapterProperties = mAdapterProperties;
            if ((adapterService == null) || (adapterProperties == null)) {
                errorLog("Received message in PendingCommandState after cleanup: " + msg.what);
                return false;
            }

            debugLog("Current state: PENDING_COMMAND, message: " + msg.what);

            switch (msg.what) {
                case USER_TURN_ON:
                    if (isBleTurningOff || isTurningOff) { //TODO:do we need to send it after ble turn off also??
                        infoLog("Deferring USER_TURN_ON request...");
                        deferMessage(msg);
                    }
                    break;

                case USER_TURN_OFF:
                    if (isTurningOn || isBleTurningOn) {
                        infoLog("Deferring USER_TURN_OFF request...");
                        deferMessage(msg);
                    }
                    break;

                case BLE_TURN_ON:
                    if (isTurningOff || isBleTurningOff) {
                        infoLog("Deferring BLE_TURN_ON request...");
                        deferMessage(msg);
                    }
                    break;

                case BLE_TURN_OFF:
                    if (isTurningOn || isBleTurningOn) {
                        infoLog("Deferring BLE_TURN_OFF request...");
                        deferMessage(msg);
                    }
                    break;

                case BLE_STARTED:
                    //Remove start timeout
                    removeMessages(BLE_START_TIMEOUT);

                    //Enable
                    boolean isGuest = UserManager.get(mAdapterService).isGuestUser();
                    if (!adapterService.enableNative(isGuest)) {
                        errorLog("Error while turning Bluetooth on");
                        notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                        transitionTo(mOffState);
                    } else {
                        sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
                    }
                    break;

                case BREDR_STARTED:
                    //Remove start timeout
                    removeMessages(BREDR_START_TIMEOUT);
                    adapterProperties.onBluetoothReady();
                    mPendingCommandState.setTurningOn(false);
                    transitionTo(mOnState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_ON);
                    break;

                case ENABLED_READY:
                    removeMessages(ENABLE_TIMEOUT);
                    mPendingCommandState.setBleTurningOn(false);
                    transitionTo(mBleOnState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
                    break;

                case SET_SCAN_MODE_TIMEOUT:
                     warningLog("Timeout while setting scan mode. Continuing with disable...");
                     //Fall through
                case BEGIN_DISABLE:
                    removeMessages(SET_SCAN_MODE_TIMEOUT);
                    sendMessageDelayed(BREDR_STOP_TIMEOUT, BREDR_STOP_TIMEOUT_DELAY);
                    adapterService.stopProfileServices();
                    break;

                case DISABLED:
                    if (isTurningOn) {
                        removeMessages(ENABLE_TIMEOUT);
                        errorLog("Error enabling Bluetooth - hardware init failed?");
                        mPendingCommandState.setTurningOn(false);
                        transitionTo(mOffState);
                        adapterService.stopProfileServices();
                        notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                        break;
                    }
                    removeMessages(DISABLE_TIMEOUT);
                    sendMessageDelayed(BLE_STOP_TIMEOUT, BLE_STOP_TIMEOUT_DELAY);
                    if (adapterService.stopGattProfileService()) {
                        debugLog("Stopping Gatt profile services that were post enabled");
                        break;
                    }
                    //Fall through if no services or services already stopped
                case BLE_STOPPED:
                    removeMessages(BLE_STOP_TIMEOUT);
                    setBleTurningOff(false);
                    transitionTo(mOffState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                    break;

                case BREDR_STOPPED:
                    removeMessages(BREDR_STOP_TIMEOUT);
                    setTurningOff(false);
                    transitionTo(mBleOnState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
                    break;

                case BLE_START_TIMEOUT:
                    errorLog("Error enabling Bluetooth (BLE start timeout)");
                    mPendingCommandState.setBleTurningOn(false);
                    transitionTo(mOffState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                    break;

                case BREDR_START_TIMEOUT:
                    errorLog("Error enabling Bluetooth (start timeout)");
                    mPendingCommandState.setTurningOn(false);
                    transitionTo(mBleOnState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
                    break;

                case ENABLE_TIMEOUT:
                    errorLog("Error enabling Bluetooth (enable timeout)");
                    mPendingCommandState.setBleTurningOn(false);
                    transitionTo(mOffState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                    break;

                case BREDR_STOP_TIMEOUT:
                    errorLog("Error stopping Bluetooth profiles (stop timeout)");
                    mPendingCommandState.setTurningOff(false);
                    transitionTo(mBleOnState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_ON);
                    break;

                case BLE_STOP_TIMEOUT:
                    errorLog("Error stopping Bluetooth profiles (BLE stop timeout)");
                    mPendingCommandState.setTurningOff(false);
                    transitionTo(mOffState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                    break;

                case DISABLE_TIMEOUT:
                    errorLog("Error disabling Bluetooth (disable timeout)");
                    if (isTurningOn)
                        mPendingCommandState.setTurningOn(false);
                    adapterService.stopProfileServices();
                    adapterService.stopGattProfileService();
                    mPendingCommandState.setTurningOff(false);
                    setBleTurningOff(false);
                    transitionTo(mOffState);
                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                    break;

                default:
                    return false;
            }
            return true;
        }
    }

    private void notifyAdapterStateChange(int newState) {
        AdapterService adapterService = mAdapterService;
        AdapterProperties adapterProperties = mAdapterProperties;
        if ((adapterService == null) || (adapterProperties == null)) {
            errorLog("notifyAdapterStateChange after cleanup:" + newState);
            return;
        }

        int oldState = adapterProperties.getState();
        adapterProperties.setState(newState);
        infoLog("Bluetooth adapter state changed: " + oldState + "-> " + newState);
        adapterService.updateAdapterState(oldState, newState);
    }

    void stateChangeCallback(int status) {
        if (status == AbstractionLayer.BT_STATE_OFF) {
            sendMessage(DISABLED);

        } else if (status == AbstractionLayer.BT_STATE_ON) {
            // We should have got the property change for adapter and remote devices.
            sendMessage(ENABLED_READY);

        } else {
            errorLog("Incorrect status in stateChangeCallback");
        }
    }

    private void infoLog(String msg) {
        if (DBG) Log.i(TAG, msg);
    }

    private void debugLog(String msg) {
        if (DBG) Log.d(TAG, msg);
    }

    private void warningLog(String msg) {
        if (DBG) Log.d(TAG, msg);
    }

    private void verboseLog(String msg) {
        if (VDBG) Log.v(TAG, msg);
    }

    private void errorLog(String msg) {
        Log.e(TAG, msg);
    }

}
