/*
 * 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.google.android.car.kitchensink.sensor;

import static java.lang.Integer.toHexString;

import android.Manifest;
import android.annotation.Nullable;
import android.car.Car;
import android.car.CarNotConnectedException;
import android.car.hardware.CarSensorConfig;
import android.car.hardware.CarSensorEvent;
import android.car.hardware.CarSensorManager;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.fragment.app.Fragment;

import com.google.android.car.kitchensink.KitchenSinkActivity;
import com.google.android.car.kitchensink.R;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class SensorsTestFragment extends Fragment {
    private static final String TAG = "CAR.SENSOR.KS";
    private static final boolean DBG = true;
    private static final boolean DBG_VERBOSE = true;
    private static final int KS_PERMISSIONS_REQUEST = 1;

    private final static String[] REQUIRED_PERMISSIONS = new String[]{
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Car.PERMISSION_MILEAGE,
        Car.PERMISSION_ENERGY,
        Car.PERMISSION_SPEED,
        Car.PERMISSION_CAR_DYNAMICS_STATE
    };

    private final CarSensorManager.OnSensorChangedListener mOnSensorChangedListener =
            new CarSensorManager.OnSensorChangedListener() {
                @Override
                public void onSensorChanged(CarSensorEvent event) {
                    if (DBG_VERBOSE) {
                        Log.v(TAG, "New car sensor event: " + event);
                    }
                    synchronized (SensorsTestFragment.this) {
                        mEventMap.put(event.sensorType, event);
                    }
                    refreshUi();
                }
            };
    private final Handler mHandler = new Handler();
    private final Map<Integer, CarSensorEvent> mEventMap = new ConcurrentHashMap<>();
    private final DateFormat mDateFormat = SimpleDateFormat.getDateTimeInstance();

    private KitchenSinkActivity mActivity;
    private TextView mSensorInfo;
    private Car mCar;
    private CarSensorManager mSensorManager;
    private String mNaString;
    private int[] supportedSensors = new int[0];
    private Set<String> mActivePermissions = new HashSet<String>();

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        if (DBG) {
            Log.i(TAG, "onCreateView");
        }

        View view = inflater.inflate(R.layout.sensors, container, false);
        mActivity = (KitchenSinkActivity) getHost();
        mSensorInfo = (TextView) view.findViewById(R.id.sensor_info);
        mNaString = getContext().getString(R.string.sensor_na);
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        final Runnable r = () -> {
            initPermissions();
        };
        ((KitchenSinkActivity) getActivity()).requestRefreshManager(r,
                new Handler(getContext().getMainLooper()));
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mSensorManager != null) {
            mSensorManager.unregisterListener(mOnSensorChangedListener);
        }
    }

    private void initSensors() {
        try {
            mSensorManager =
                (CarSensorManager) ((KitchenSinkActivity) getActivity()).getSensorManager();
            supportedSensors = mSensorManager.getSupportedSensors();
            for (Integer sensor : supportedSensors) {
                mSensorManager.registerListener(mOnSensorChangedListener, sensor,
                        CarSensorManager.SENSOR_RATE_NORMAL);
            }
        } catch (CarNotConnectedException e) {
            Log.e(TAG, "Car not connected or not supported", e);
        } catch (Exception e) {
            Log.e(TAG, "initSensors() exception caught: ", e);
        }
    }

    private void initPermissions() {
        Set<String> missingPermissions = checkExistingPermissions();
        if (!missingPermissions.isEmpty()) {
            requestPermissions(missingPermissions);
        } else {
            initSensors();
        }
    }

    private Set<String> checkExistingPermissions() {
        Set<String> missingPermissions = new HashSet<String>();
        for (String permission : REQUIRED_PERMISSIONS) {
            if (mActivity.checkSelfPermission(permission)
                == PackageManager.PERMISSION_GRANTED) {
                mActivePermissions.add(permission);
            } else {
                missingPermissions.add(permission);
            }
        }
        return missingPermissions;
    }

    private void requestPermissions(Set<String> permissions) {
        Log.d(TAG, "requesting additional permissions=" + permissions);

        requestPermissions(permissions.toArray(new String[permissions.size()]),
                KS_PERMISSIONS_REQUEST);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions,
            int[] grantResults) {
        Log.d(TAG, "onRequestPermissionsResult reqCode=" + requestCode);
        if (KS_PERMISSIONS_REQUEST == requestCode) {
            for (int i=0; i<permissions.length; i++) {
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    mActivePermissions.add(permissions[i]);
                }
            }
            initSensors();
        }
    }

    private void refreshUi() {
        String summaryString;
        synchronized (this) {
            List<String> summary = new ArrayList<>();
            for (Integer i : supportedSensors) {
                CarSensorEvent event = mEventMap.get(i);
                switch (i) {
                    case CarSensorManager.SENSOR_TYPE_CAR_SPEED:
                        summary.add(getContext().getString(R.string.sensor_speed,
                                getTimestamp(event),
                                event == null ? mNaString : event.getCarSpeedData(null).carSpeed));
                        break;
                    case CarSensorManager.SENSOR_TYPE_RPM:
                        summary.add(getContext().getString(R.string.sensor_rpm,
                                getTimestamp(event),
                                event == null ? mNaString : event.getRpmData(null).rpm));
                        break;
                    case CarSensorManager.SENSOR_TYPE_ODOMETER:
                        summary.add(getContext().getString(R.string.sensor_odometer,
                                getTimestamp(event),
                                event == null ? mNaString : event.getOdometerData(null).kms));
                        break;
                    case CarSensorManager.SENSOR_TYPE_FUEL_LEVEL:
                        summary.add(getFuelLevel(event));
                        break;
                    case CarSensorManager.SENSOR_TYPE_FUEL_DOOR_OPEN:
                        summary.add(getFuelDoorOpen(event));
                        break;
                    case CarSensorManager.SENSOR_TYPE_IGNITION_STATE:
                        summary.add(getContext().getString(R.string.sensor_ignition_status,
                                getTimestamp(event),
                                event == null ? mNaString :
                                event.getIgnitionStateData(null).ignitionState));
                        break;
                    case CarSensorManager.SENSOR_TYPE_PARKING_BRAKE:
                        summary.add(getContext().getString(R.string.sensor_parking_brake,
                                getTimestamp(event),
                                event == null ? mNaString :
                                event.getParkingBrakeData(null).isEngaged));
                        break;
                    case CarSensorManager.SENSOR_TYPE_GEAR:
                        summary.add(getContext().getString(R.string.sensor_gear,
                                getTimestamp(event),
                                event == null ? mNaString : event.getGearData(null).gear));
                        break;
                    case CarSensorManager.SENSOR_TYPE_NIGHT:
                        summary.add(getContext().getString(R.string.sensor_night,
                                getTimestamp(event),
                                event == null ? mNaString : event.getNightData(null).isNightMode));
                        break;
                    case CarSensorManager.SENSOR_TYPE_ENV_OUTSIDE_TEMPERATURE:
                        String temperature = mNaString;
                        if (event != null) {
                            CarSensorEvent.EnvironmentData env = event.getEnvironmentData(null);
                            temperature = Float.isNaN(env.temperature) ? temperature :
                                    String.valueOf(env.temperature);
                        }
                        summary.add(getContext().getString(R.string.sensor_environment,
                                getTimestamp(event), temperature));
                        break;
                    case CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE:
                        if(event != null) {
                            CarSensorEvent.CarWheelTickDistanceData d =
                                    event.getCarWheelTickDistanceData(null);
                            summary.add(getContext().getString(R.string.sensor_wheel_ticks,
                                getTimestamp(event), d.sensorResetCount, d.frontLeftWheelDistanceMm,
                                d.frontRightWheelDistanceMm, d.rearLeftWheelDistanceMm,
                                d.rearRightWheelDistanceMm));
                        } else {
                            summary.add(getContext().getString(R.string.sensor_wheel_ticks,
                                getTimestamp(event), mNaString, mNaString, mNaString, mNaString,
                                mNaString));
                        }
                        // Get the config data
                        try {
                            CarSensorConfig c = mSensorManager.getSensorConfig(
                                CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE);
                            summary.add(getContext().getString(R.string.sensor_wheel_ticks_cfg,
                                c.getInt(CarSensorConfig.WHEEL_TICK_DISTANCE_SUPPORTED_WHEELS),
                                c.getInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_LEFT_UM_PER_TICK),
                                c.getInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_RIGHT_UM_PER_TICK),
                                c.getInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_LEFT_UM_PER_TICK),
                                c.getInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_RIGHT_UM_PER_TICK)));
                        } catch (CarNotConnectedException e) {
                            Log.e(TAG, "Car not connected or not supported", e);
                        }
                        break;
                    case CarSensorManager.SENSOR_TYPE_ABS_ACTIVE:
                        summary.add(getContext().getString(R.string.sensor_abs_is_active,
                            getTimestamp(event), event == null ? mNaString :
                                    event.getCarAbsActiveData(null).absIsActive));
                        break;

                    case CarSensorManager.SENSOR_TYPE_TRACTION_CONTROL_ACTIVE:
                        summary.add(
                            getContext().getString(R.string.sensor_traction_control_is_active,
                            getTimestamp(event), event == null ? mNaString :
                                    event.getCarTractionControlActiveData(null)
                                    .tractionControlIsActive));
                        break;
                    case CarSensorManager.SENSOR_TYPE_EV_BATTERY_LEVEL:
                        summary.add(getEvBatteryLevel(event));
                        break;
                    case CarSensorManager.SENSOR_TYPE_EV_CHARGE_PORT_OPEN:
                        summary.add(getEvChargePortOpen(event));
                        break;
                    case CarSensorManager.SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED:
                        summary.add(getEvChargePortConnected(event));
                        break;
                    case CarSensorManager.SENSOR_TYPE_EV_BATTERY_CHARGE_RATE:
                        summary.add(getEvChargeRate(event));
                        break;
                    default:
                        // Should never happen.
                        Log.w(TAG, "Unrecognized event type: " + toHexString(i));
                }
            }
            summaryString = TextUtils.join("\n", summary);
        }
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mSensorInfo.setText(summaryString);
            }
        });
    }

    private String getTimestamp(CarSensorEvent event) {
        if (event == null) {
            return mNaString;
        }
        return mDateFormat.format(new Date(event.timestamp / (1000L * 1000L)));
    }

    private String getFuelLevel(CarSensorEvent event) {
        String fuelLevel = mNaString;
        if(event != null) {
            fuelLevel = String.valueOf(event.getFuelLevelData(null).level);
        }
        return getContext().getString(R.string.sensor_fuel_level, getTimestamp(event), fuelLevel);
    }

    private String getFuelDoorOpen(CarSensorEvent event) {
        String fuelDoorOpen = mNaString;
        if(event != null) {
            fuelDoorOpen = String.valueOf(event.getCarFuelDoorOpenData(null).fuelDoorIsOpen);
        }
        return getContext().getString(R.string.sensor_fuel_door_open, getTimestamp(event),
            fuelDoorOpen);
    }

    private String getEvBatteryLevel(CarSensorEvent event) {
        String evBatteryLevel = mNaString;
        if(event != null) {
            evBatteryLevel = String.valueOf(event.getCarEvBatteryLevelData(null).evBatteryLevel);
        }
        return getContext().getString(R.string.sensor_ev_battery_level, getTimestamp(event),
            evBatteryLevel);
    }

    private String getEvChargePortOpen(CarSensorEvent event) {
        String evChargePortOpen = mNaString;
        if(event != null) {
            evChargePortOpen = String.valueOf(
                event.getCarEvChargePortOpenData(null).evChargePortIsOpen);
        }
        return getContext().getString(R.string.sensor_ev_charge_port_is_open, getTimestamp(event),
            evChargePortOpen);
    }

    private String getEvChargePortConnected(CarSensorEvent event) {
        String evChargePortConnected = mNaString;
        if(event != null) {
            evChargePortConnected = String.valueOf(
                event.getCarEvChargePortConnectedData(null).evChargePortIsConnected);
        }
        return getContext().getString(R.string.sensor_ev_charge_port_is_connected,
            getTimestamp(event), evChargePortConnected);
    }

    private String getEvChargeRate(CarSensorEvent event) {
        String evChargeRate = mNaString;
        if(event != null) {
            evChargeRate = String.valueOf(event.getCarEvBatteryChargeRateData(null).evChargeRate);
        }
        return getContext().getString(R.string.sensor_ev_charge_rate, getTimestamp(event),
            evChargeRate);
    }
}
