/*
 * Copyright (c) 2016, 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.car.hvac;

import android.app.Service;
import android.car.Car;
import android.car.CarNotConnectedException;
import android.car.VehicleAreaSeat;
import android.car.VehicleAreaWindow;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.hvac.CarHvacManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

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

import javax.annotation.concurrent.GuardedBy;

public class HvacController extends Service {
    private static final String TAG = "HvacController";
    private static final int DRIVER_ZONE_ID = VehicleAreaSeat.SEAT_ROW_1_LEFT |
            VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER;
    private static final int PASSENGER_ZONE_ID = VehicleAreaSeat.SEAT_ROW_1_RIGHT |
            VehicleAreaSeat.SEAT_ROW_2_RIGHT;

    public static final int[] AIRFLOW_STATES = new int[]{
            CarHvacManager.FAN_DIRECTION_FACE,
            CarHvacManager.FAN_DIRECTION_FLOOR,
            (CarHvacManager.FAN_DIRECTION_FACE | CarHvacManager.FAN_DIRECTION_FLOOR)
    };
    // Hardware specific value for the front seats
    public static final int SEAT_ALL = DRIVER_ZONE_ID | PASSENGER_ZONE_ID;

    /**
     * Callback for receiving updates from the hvac manager. A Callback can be
     * registered using {@link #registerCallback}.
     */
    public static abstract class Callback {

        public void onPassengerTemperatureChange(CarPropertyValue propValue) {
        }

        public void onDriverTemperatureChange(CarPropertyValue propValue) {
        }

        public void onFanSpeedChange(int position) {
        }

        public void onAcStateChange(boolean isOn) {
        }

        public void onFrontDefrosterChange(boolean isOn) {
        }

        public void onRearDefrosterChange(boolean isOn) {
        }

        public void onPassengerSeatWarmerChange(int level) {
        }

        public void onDriverSeatWarmerChange(int level) {
        }

        public void onFanDirectionChange(int direction) {
        }

        public void onAirCirculationChange(boolean isOn) {
        }

        public void onAutoModeChange(boolean isOn) {
        }

        public void onHvacPowerChange(boolean isOn) {
        }
    }

    public class LocalBinder extends Binder {
        HvacController getService() {
            return HvacController.this;
        }
    }

    private final Binder mBinder = new LocalBinder();

    private Car mCarApiClient;
    private CarHvacManager mHvacManager;
    private Object mHvacManagerReady = new Object();

    private HvacPolicy mPolicy;
    @GuardedBy("mCallbacks")
    private List<Callback> mCallbacks = new ArrayList<>();
    private DataStore mDataStore = new DataStore();

    @Override
    public void onCreate() {
        super.onCreate();
        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
            mCarApiClient = Car.createCar(this, mCarServiceConnection);
            mCarApiClient.connect();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mHvacManager != null) {
            mHvacManager.unregisterCallback(mHardwareCallback);
        }
        if (mCarApiClient != null) {
            mCarApiClient.disconnect();
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public void registerCallback(Callback callback) {
        synchronized (mCallbacks) {
            mCallbacks.add(callback);
        }
    }

    public void unregisterCallback(Callback callback) {
        synchronized (mCallbacks) {
            mCallbacks.remove(callback);
        }
    }

    private void initHvacManager(CarHvacManager carHvacManager) {
        mHvacManager = carHvacManager;
        List<CarPropertyConfig> properties = null;
        try {
            properties = mHvacManager.getPropertyList();
            mPolicy = new HvacPolicy(HvacController.this, properties);
            mHvacManager.registerCallback(mHardwareCallback);
        } catch (CarNotConnectedException e) {
            Log.e(TAG, "Car not connected in HVAC");
        }

    }

    private final ServiceConnection mCarServiceConnection =
            new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    synchronized (mHvacManagerReady) {
                        try {
                            initHvacManager((CarHvacManager) mCarApiClient.getCarManager(
                                    Car.HVAC_SERVICE));
                            mHvacManagerReady.notifyAll();
                        } catch (CarNotConnectedException e) {
                            Log.e(TAG, "Car not connected in onServiceConnected");
                        }
                    }
                }

                @Override
                public void onServiceDisconnected(ComponentName name) {
                }
            };

    private final CarHvacManager.CarHvacEventCallback mHardwareCallback =
            new CarHvacManager.CarHvacEventCallback() {
                @Override
                public void onChangeEvent(final CarPropertyValue val) {
                    int areaId = val.getAreaId();
                    switch (val.getPropertyId()) {
                        case CarHvacManager.ID_ZONED_AC_ON:
                            handleAcStateUpdate(getValue(val));
                            break;
                        case CarHvacManager.ID_ZONED_FAN_DIRECTION:
                            handleFanPositionUpdate(areaId, getValue(val));
                            break;
                        case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT:
                            handleFanSpeedUpdate(areaId, getValue(val));
                            break;
                        case CarHvacManager.ID_ZONED_TEMP_SETPOINT:
                            handleTempUpdate(val);
                            break;
                        case CarHvacManager.ID_WINDOW_DEFROSTER_ON:
                            handleDefrosterUpdate(areaId, getValue(val));
                            break;
                        case CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON:
                            handleAirCirculationUpdate(getValue(val));
                            break;
                        case CarHvacManager.ID_ZONED_SEAT_TEMP:
                            handleSeatWarmerUpdate(areaId, getValue(val));
                            break;
                        case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON:
                            handleAutoModeUpdate(getValue(val));
                            break;
                        case CarHvacManager.ID_ZONED_HVAC_POWER_ON:
                            handleHvacPowerOn(getValue(val));
                            break;
                        default:
                            if (Log.isLoggable(TAG, Log.DEBUG)) {
                                Log.d(TAG, "Unhandled HVAC event, id: " + val.getPropertyId());
                            }
                    }
                }

                @Override
                public void onErrorEvent(final int propertyId, final int zone) {
                }
            };

    @SuppressWarnings("unchecked")
    public static <E> E getValue(CarPropertyValue propertyValue) {
        return (E) propertyValue.getValue();
    }

    public static boolean isAvailable(CarPropertyValue propertyValue) {
        return propertyValue.getStatus() == CarPropertyValue.STATUS_AVAILABLE;
    }

    void handleHvacPowerOn(boolean isOn) {
        boolean shouldPropagate = mDataStore.shouldPropagateHvacPowerUpdate(isOn);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Hvac Power On: " + isOn + " should propagate: " + shouldPropagate);
        }
        if (shouldPropagate) {
            synchronized (mCallbacks) {
                for (int i = 0; i < mCallbacks.size(); i++) {
                    mCallbacks.get(i).onHvacPowerChange(isOn);
                }
            }
        }
    }

    void handleSeatWarmerUpdate(int zone, int level) {
        boolean shouldPropagate = mDataStore.shouldPropagateSeatWarmerLevelUpdate(zone, level);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Seat Warmer Update, zone: " + zone + " level: " + level +
                    " should propagate: " + shouldPropagate);
        }
        if (shouldPropagate) {
            synchronized (mCallbacks) {
                for (int i = 0; i < mCallbacks.size(); i++) {
                    if (zone == VehicleAreaSeat.SEAT_ROW_1_LEFT) {
                        mCallbacks.get(i).onDriverSeatWarmerChange(level);
                    } else {
                        mCallbacks.get(i).onPassengerSeatWarmerChange(level);
                    }
                }
            }
        }
    }

    private void handleAirCirculationUpdate(boolean airCirculationState) {
        boolean shouldPropagate
                = mDataStore.shouldPropagateAirCirculationUpdate(airCirculationState);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Air Circulation Update: " + airCirculationState +
                    " should propagate: " + shouldPropagate);
        }
        if (shouldPropagate) {
            synchronized (mCallbacks) {
                for (int i = 0; i < mCallbacks.size(); i++) {
                    mCallbacks.get(i).onAirCirculationChange(airCirculationState);
                }
            }
        }
    }

    private void handleAutoModeUpdate(boolean autoModeState) {
        boolean shouldPropagate = mDataStore.shouldPropagateAutoModeUpdate(autoModeState);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "AutoMode Update, id: " + autoModeState +
                    " should propagate: " + shouldPropagate);
        }
        if (shouldPropagate) {
            synchronized (mCallbacks) {
                for (int i = 0; i < mCallbacks.size(); i++) {
                    mCallbacks.get(i).onAutoModeChange(autoModeState);
                }
            }
        }
    }

    private void handleAcStateUpdate(boolean acState) {
        boolean shouldPropagate = mDataStore.shouldPropagateAcUpdate(acState);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "AC State Update, id: " + acState +
                    " should propagate: " + shouldPropagate);
        }
        if (shouldPropagate) {
            synchronized (mCallbacks) {
                for (int i = 0; i < mCallbacks.size(); i++) {
                    mCallbacks.get(i).onAcStateChange(acState);
                }
            }
        }
    }

    private void handleFanPositionUpdate(int zone, int position) {
        int index = fanPositionToAirflowIndex(position);
        boolean shouldPropagate = mDataStore.shouldPropagateFanPositionUpdate(zone, index);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Fan Position Update, zone: " + zone + " position: " + position +
                    " should propagate: " + shouldPropagate);
        }
        if (shouldPropagate) {
            synchronized (mCallbacks) {
                for (int i = 0; i < mCallbacks.size(); i++) {
                    mCallbacks.get(i).onFanDirectionChange(position);
                }
            }
        }
    }

    private void handleFanSpeedUpdate(int zone, int speed) {
        boolean shouldPropagate = mDataStore.shouldPropagateFanSpeedUpdate(zone, speed);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Fan Speed Update, zone: " + zone + " speed: " + speed +
                    " should propagate: " + shouldPropagate);
        }
        if (shouldPropagate) {
            synchronized (mCallbacks) {
                for (int i = 0; i < mCallbacks.size(); i++) {
                    mCallbacks.get(i).onFanSpeedChange(speed);
                }
            }
        }
    }

    private void handleTempUpdate(CarPropertyValue value) {
        final int zone = value.getAreaId();
        final float temp = (Float) value.getValue();
        final boolean available = value.getStatus() == CarPropertyValue.STATUS_AVAILABLE;
        boolean shouldPropagate = mDataStore.shouldPropagateTempUpdate(zone, temp, available);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Temp Update, zone: " + zone + " temp: " + temp +
                    "available: " + available + " should propagate: " + shouldPropagate);
        }
        if (shouldPropagate) {
            synchronized (mCallbacks) {
                for (int i = 0; i < mCallbacks.size(); i++) {
                    if (zone == DRIVER_ZONE_ID) {
                        mCallbacks.get(i)
                                .onDriverTemperatureChange(value);
                    } else if (zone == PASSENGER_ZONE_ID) {
                        mCallbacks.get(i)
                                .onPassengerTemperatureChange(value);
                    } else {
                        Log.w(TAG, "Unknown temperature set area id: " + zone);
                    }
                }
            }
        }
    }

    private void handleDefrosterUpdate(int zone, boolean defrosterState) {
        boolean shouldPropagate = mDataStore.shouldPropagateDefrosterUpdate(zone, defrosterState);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Defroster Update, zone: " + zone + " state: " + defrosterState +
                    " should propagate: " + shouldPropagate);
        }
        if (shouldPropagate) {
            synchronized (mCallbacks) {
                for (int i = 0; i < mCallbacks.size(); i++) {
                    if (zone == VehicleAreaWindow.WINDOW_FRONT_WINDSHIELD) {
                        mCallbacks.get(i).onFrontDefrosterChange(defrosterState);
                    } else if (zone == VehicleAreaWindow.WINDOW_REAR_WINDSHIELD) {
                        mCallbacks.get(i).onRearDefrosterChange(defrosterState);
                    }
                }
            }
        }
    }

    public void requestRefresh(final Runnable r, final Handler h) {
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... unused) {
                synchronized (mHvacManagerReady) {
                    while (mHvacManager == null) {
                        try {
                            mHvacManagerReady.wait();
                        } catch (InterruptedException e) {
                            // We got interrupted so we might be shutting down.
                            return null;
                        }
                    }
                }
                fetchTemperature(DRIVER_ZONE_ID);
                fetchTemperature(PASSENGER_ZONE_ID);
                fetchFanSpeed();
                fetchDefrosterState(VehicleAreaWindow.WINDOW_FRONT_WINDSHIELD);
                fetchDefrosterState(VehicleAreaWindow.WINDOW_REAR_WINDSHIELD);
                fetchAirflow();
                fetchAcState();
                fetchAirCirculation();
                fetchHvacPowerState();
                return null;
            }

            @Override
            protected void onPostExecute(Void unused) {
                h.post(r);
            }
        };
        task.execute();
    }

    public HvacPolicy getPolicy() {
        return mPolicy;
    }

    public boolean isTemperatureControlAvailable(int zone) {
        if (mHvacManager != null) {
            try {
                return mHvacManager.isPropertyAvailable(
                        CarHvacManager.ID_ZONED_TEMP_SETPOINT, zone);
            } catch (android.car.CarNotConnectedException e) {
                Log.e(TAG, "Car not connected in isTemperatureControlAvailable");
            }
        }

        return false;
    }

    public boolean isDriverTemperatureControlAvailable() {
        return isTemperatureControlAvailable(DRIVER_ZONE_ID);
    }

    public boolean isPassengerTemperatureControlAvailable() {
        return isTemperatureControlAvailable(PASSENGER_ZONE_ID);
    }

    private void fetchTemperature(int zone) {
        if (mHvacManager != null) {
            try {
                float value = mHvacManager.getFloatProperty(
                        CarHvacManager.ID_ZONED_TEMP_SETPOINT, zone);
                boolean available = mHvacManager.isPropertyAvailable(
                        CarHvacManager.ID_ZONED_TEMP_SETPOINT, zone);
                mDataStore.setTemperature(zone, value, available);
            } catch (android.car.CarNotConnectedException e) {
                Log.e(TAG, "Car not connected in fetchTemperature");
            }
        }
    }

    public int getDriverTemperature() {
        return Float.valueOf(mDataStore.getTemperature(DRIVER_ZONE_ID)).intValue();
    }

    public int getPassengerTemperature() {
        return Float.valueOf(mDataStore.getTemperature(PASSENGER_ZONE_ID)).intValue();
    }

    public void setDriverTemperature(int temperature) {
        setTemperature(DRIVER_ZONE_ID, temperature);
    }

    public void setPassengerTemperature(int temperature) {
        setTemperature(PASSENGER_ZONE_ID, temperature);
    }

    public void setTemperature(final int zone, final float temperature) {
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    try {
                        mHvacManager.setFloatProperty(
                                CarHvacManager.ID_ZONED_TEMP_SETPOINT, zone, temperature);
                        // if the set() succeeds, consider the property available
                        mDataStore.setTemperature(zone, temperature, true);
                    } catch (android.car.CarNotConnectedException e) {
                        Log.e(TAG, "Car not connected in setTemperature");
                    } catch (Exception e) {
                        Log.e(TAG, "set temp failed", e);
                    }
                }
                return null;
            }
        };
        task.execute();
    }

    public void setHvacPowerState(final boolean state) {
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    try {
                        mHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_HVAC_POWER_ON,
                                SEAT_ALL, state);
                        // if the set() succeeds, consider the property available
                        mDataStore.setHvacPowerState(state);
                    } catch (android.car.CarNotConnectedException e) {
                        Log.e(TAG, "Car not connected in setHvacPowerState");
                    } catch (Exception e) {
                        Log.e(TAG, "set power failed", e);
                    }
                }
                return null;
            }
        };
        task.execute();
    }

    public void setDriverSeatWarmerLevel(int level) {
        setSeatWarmerLevel(VehicleAreaSeat.SEAT_ROW_1_LEFT, level);
    }

    public void setPassengerSeatWarmerLevel(int level) {
        setSeatWarmerLevel(VehicleAreaSeat.SEAT_ROW_1_RIGHT, level);
    }

    public void setSeatWarmerLevel(final int zone, final int level) {
        mDataStore.setSeatWarmerLevel(zone, level);
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    try {
                        mHvacManager.setIntProperty(
                                CarHvacManager.ID_ZONED_SEAT_TEMP, zone, level);
                    } catch (android.car.CarNotConnectedException e) {
                        Log.e(TAG, "Car not connected in setSeatWarmerLevel");
                    } catch (Exception e) {
                        Log.e(TAG, "set seat warmer failed", e);
                    }
                }
                return null;
            }
        };
        task.execute();
    }

    private void fetchFanSpeed() {
        if (mHvacManager != null) {
            int zone = SEAT_ALL; // Car specific workaround.
            try {
                mDataStore.setFanSpeed(mHvacManager.getIntProperty(
                        CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, zone));
            } catch (android.car.CarNotConnectedException e) {
                Log.e(TAG, "Car not connected in fetchFanSpeed");
            }
        }
    }

    public int getFanSpeed() {
        return mDataStore.getFanSpeed();
    }

    public void setFanSpeed(final int fanSpeed) {
        mDataStore.setFanSpeed(fanSpeed);

        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            int newFanSpeed;

            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    int zone = SEAT_ALL; // Car specific workaround.
                    try {
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
                            Log.d(TAG, "Setting fanspeed to: " + fanSpeed);
                        }
                        mHvacManager.setIntProperty(
                                CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, zone, fanSpeed);

                        newFanSpeed = mHvacManager.getIntProperty(
                                CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, zone);
                    } catch (android.car.CarNotConnectedException e) {
                        Log.e(TAG, "Car not connected in setFanSpeed");
                    }
                }
                return null;
            }

            @Override
            protected void onPostExecute(final Void result) {
                Log.e(TAG, "postExecute new fanSpeed: " + newFanSpeed);
            }
        };
        task.execute();
    }

    private void fetchDefrosterState(int zone) {
        if (mHvacManager != null) {
            try {
                mDataStore.setDefrosterState(zone, mHvacManager.getBooleanProperty(
                        CarHvacManager.ID_WINDOW_DEFROSTER_ON, zone));
            } catch (android.car.CarNotConnectedException e) {
                Log.e(TAG, "Car not connected in fetchDefrosterState");
            }
        }
    }

    public boolean getFrontDefrosterState() {
        return mDataStore.getDefrosterState(VehicleAreaWindow.WINDOW_FRONT_WINDSHIELD);
    }

    public boolean getRearDefrosterState() {
        return mDataStore.getDefrosterState(VehicleAreaWindow.WINDOW_REAR_WINDSHIELD);
    }

    public void setFrontDefrosterState(boolean state) {
        setDefrosterState(VehicleAreaWindow.WINDOW_FRONT_WINDSHIELD, state);
    }

    public void setRearDefrosterState(boolean state) {
        setDefrosterState(VehicleAreaWindow.WINDOW_REAR_WINDSHIELD, state);
    }

    public void setDefrosterState(final int zone, final boolean state) {
        mDataStore.setDefrosterState(zone, state);
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    try {
                        mHvacManager.setBooleanProperty(
                                CarHvacManager.ID_WINDOW_DEFROSTER_ON, zone, state);
                    } catch (android.car.CarNotConnectedException e) {
                        Log.e(TAG, "Car not connected in setDeforsterState");
                    }
                }
                return null;
            }
        };
        task.execute();
    }

    private void fetchAcState() {
        if (mHvacManager != null) {
            try {
                mDataStore.setAcState(mHvacManager.getBooleanProperty(CarHvacManager.ID_ZONED_AC_ON,
                        SEAT_ALL));
            } catch (android.car.CarNotConnectedException e) {
                Log.e(TAG, "Car not connected in fetchAcState");
            }
        }
    }

    public boolean getAcState() {
        return mDataStore.getAcState();
    }

    public void setAcState(final boolean state) {
        mDataStore.setAcState(state);
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    try {
                        mHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_AC_ON,
                                SEAT_ALL, state);
                    } catch (android.car.CarNotConnectedException e) {
                        Log.e(TAG, "Car not connected in setAcState");
                    }
                }
                return null;
            }
        };
        task.execute();
    }

    private int fanPositionToAirflowIndex(int fanPosition) {
        for (int i = 0; i < AIRFLOW_STATES.length; i++) {
            if (fanPosition == AIRFLOW_STATES[i]) {
                return i;
            }
        }
        Log.e(TAG, "Unknown fan position " + fanPosition + ". Returning default.");
        return AIRFLOW_STATES[0];
    }

    private void fetchAirflow() {
        if (mHvacManager != null) {
            try {
                int val = mHvacManager.getIntProperty(CarHvacManager.ID_ZONED_FAN_DIRECTION,
                        SEAT_ALL);
                mDataStore.setAirflow(SEAT_ALL, fanPositionToAirflowIndex(val));
            } catch (android.car.CarNotConnectedException e) {
                Log.e(TAG, "Car not connected in fetchAirFlow");
            }
        }
    }

    public int getAirflowIndex(int zone) {
        return mDataStore.getAirflow(zone);
    }

    public void setAirflowIndex(final int zone, final int index) {
        mDataStore.setAirflow(zone, index);
        int override = SEAT_ALL; // Car specific workaround.
        int val = AIRFLOW_STATES[index];
        setFanDirection(override, val);
    }

    public void setFanDirection(final int direction) {
        mDataStore.setAirflow(SEAT_ALL, direction);
        setFanDirection(SEAT_ALL, direction);
    }

    private void setFanDirection(final int zone, final int direction) {
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    try {
                        mHvacManager.setIntProperty(
                                CarHvacManager.ID_ZONED_FAN_DIRECTION, zone, direction);
                    } catch (android.car.CarNotConnectedException e) {
                        Log.e(TAG, "Car not connected in setAirflowIndex");
                    }
                }
                return null;
            }
        };
        task.execute();
    }


    private void fetchAirCirculation() {
        if (mHvacManager != null) {
            try {
                mDataStore.setAirCirculationState(mHvacManager
                        .getBooleanProperty(CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON,
                                SEAT_ALL));
            } catch (android.car.CarNotConnectedException e) {
                Log.e(TAG, "Car not connected in fetchAirCirculationState");
            }
        }
    }

    public boolean getAirCirculationState() {
        return mDataStore.getAirCirculationState();
    }

    public void setAirCirculation(final boolean state) {
        mDataStore.setAirCirculationState(state);
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    try {
                        mHvacManager.setBooleanProperty(
                                CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON,
                                SEAT_ALL, state);
                    } catch (android.car.CarNotConnectedException e) {
                        Log.e(TAG, "Car not connected in setAcState");
                    }
                }
                return null;
            }
        };
        task.execute();
    }

    public boolean getAutoModeState() {
        return mDataStore.getAutoModeState();
    }

    public void setAutoMode(final boolean state) {
        mDataStore.setAutoModeState(state);
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    try {
                        mHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON,
                                SEAT_ALL, state);
                    } catch (android.car.CarNotConnectedException e) {
                        Log.e(TAG, "Car not connected in setAutoModeState");
                    }
                }
                return null;
            }
        };
        task.execute();
    }

    public boolean getHvacPowerState() {
        return mDataStore.getHvacPowerState();
    }

    private void fetchHvacPowerState() {
        if (mHvacManager != null) {
            try {
                mDataStore.setHvacPowerState(mHvacManager.getBooleanProperty(
                        CarHvacManager.ID_ZONED_HVAC_POWER_ON, SEAT_ALL));
            } catch (android.car.CarNotConnectedException e) {
                Log.e(TAG, "Car not connected in fetchHvacPowerState");
            }
        }
    }
}
