/*
 * 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.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);
                    }
                    refreshSensorInfoText();
                }
            };
    private final Handler mHandler = new Handler();
    private final Map<Integer, CarSensorEvent> mEventMap = new ConcurrentHashMap<>();
    private final DateFormat mDateFormat = SimpleDateFormat.getDateTimeInstance();

    private KitchenSinkActivity mActivity;
    private Car mCar;
    private CarSensorManager mCarSensorManager;
    private LocationListeners mLocationListener;
    private String mNaString;
    private int[] supportedSensors = new int[0];
    private Set<String> mActivePermissions = new HashSet<String>();

    private TextView mSensorInfo;
    private TextView mLocationInfo;
    private TextView mAccelInfo;
    private TextView mGyroInfo;
    private TextView mMagInfo;

    @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);
        mLocationInfo = (TextView) view.findViewById(R.id.location_info);
        mAccelInfo = (TextView) view.findViewById(R.id.accel_info);
        mGyroInfo = (TextView) view.findViewById(R.id.gyro_info);
        mMagInfo = (TextView) view.findViewById(R.id.mag_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 (mCarSensorManager != null) {
            mCarSensorManager.unregisterListener(mOnSensorChangedListener);
        }
        if (mLocationListener != null) {
            mLocationListener.stopListening();
        }
    }

    private void initSensors() {
        try {
            if (mCarSensorManager == null) {
                mCarSensorManager =
                    (CarSensorManager) ((KitchenSinkActivity) getActivity()).getSensorManager();
            }
            supportedSensors = mCarSensorManager.getSupportedSensors();
            for (Integer sensor : supportedSensors) {
                mCarSensorManager.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 SensorManager: ", e);
        }
        try {
            if (mLocationListener == null) {
                mLocationListener = new LocationListeners(getContext(),
                                                          new LocationInfoTextUpdateListener());
            }
            mLocationListener.startListening();
        } catch (Exception e) {
            Log.e(TAG, "initSensors() exception caught from LocationListeners: ", e);
        }
    }

    private void initPermissions() {
        Set<String> missingPermissions = checkExistingPermissions();
        if (!missingPermissions.isEmpty()) {
            requestPermissions(missingPermissions);
            // The callback with premission results will take care of calling initSensors for us
        } 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 refreshSensorInfoText() {
        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 = mCarSensorManager.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;
                    case CarSensorManager.SENSOR_TYPE_ENGINE_OIL_LEVEL:
                        summary.add(getEngineOilLevel(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 Double.toString(event.timestamp / (1000L * 1000L * 1000L)) + " seconds";
    }

    private String getTimestampNow() {
        return Double.toString(System.nanoTime() / (1000L * 1000L * 1000L)) + " seconds";
    }

    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);
    }

    private String getEngineOilLevel(CarSensorEvent event) {
        String engineOilLevel = mNaString;
        if(event != null) {
            engineOilLevel = String.valueOf(event.getCarEngineOilLevelData(null).engineOilLevel);
        }
        return  getContext().getString(R.string.sensor_oil_level, getTimestamp(event),
           engineOilLevel);
    }

    public class LocationInfoTextUpdateListener {
        public void setLocationField(String value) {
            setTimestampedTextField(mLocationInfo, value);
        }

        public void setAccelField(String value) {
            setTimestampedTextField(mAccelInfo, value);
        }

        public void setGyroField(String value) {
            setTimestampedTextField(mGyroInfo, value);
        }

        public void setMagField(String value) {
            setTimestampedTextField(mMagInfo, value);
        }

        private void setTimestampedTextField(TextView text, String value) {
            synchronized (SensorsTestFragment.this) {
                text.setText(getTimestampNow() + ": " + value);
                Log.d(TAG, "setText: " + value);
            }
        }
    }
}
