/*
 * Copyright (C) 2021 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.telemetry;

import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_NONE;
import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_PARSE_FAILED;
import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_UNKNOWN;

import android.annotation.NonNull;
import android.app.StatsManager;
import android.car.Car;
import android.car.telemetry.ICarTelemetryService;
import android.car.telemetry.ICarTelemetryServiceListener;
import android.car.telemetry.MetricsConfigKey;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.util.IndentingPrintWriter;
import android.util.Slog;

import com.android.car.CarLocalServices;
import com.android.car.CarLog;
import com.android.car.CarPropertyService;
import com.android.car.CarServiceBase;
import com.android.car.CarServiceUtils;
import com.android.car.systeminterface.SystemInterface;
import com.android.car.telemetry.databroker.DataBroker;
import com.android.car.telemetry.databroker.DataBrokerController;
import com.android.car.telemetry.databroker.DataBrokerImpl;
import com.android.car.telemetry.publisher.PublisherFactory;
import com.android.car.telemetry.publisher.StatsManagerImpl;
import com.android.car.telemetry.publisher.StatsManagerProxy;
import com.android.car.telemetry.systemmonitor.SystemMonitor;
import com.android.internal.annotations.VisibleForTesting;

import com.google.protobuf.InvalidProtocolBufferException;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

/**
 * CarTelemetryService manages OEM telemetry collection, processing and communication
 * with a data upload service.
 */
public class CarTelemetryService extends ICarTelemetryService.Stub implements CarServiceBase {

    private static final boolean DEBUG = false;
    public static final String TELEMETRY_DIR = "telemetry";

    private final Context mContext;
    private final CarPropertyService mCarPropertyService;
    private final HandlerThread mTelemetryThread = CarServiceUtils.getHandlerThread(
            CarTelemetryService.class.getSimpleName());
    private final Handler mTelemetryHandler = new Handler(mTelemetryThread.getLooper());

    private ICarTelemetryServiceListener mListener;
    private DataBroker mDataBroker;
    private DataBrokerController mDataBrokerController;
    private MetricsConfigStore mMetricsConfigStore;
    private PublisherFactory mPublisherFactory;
    private ResultStore mResultStore;
    private StatsManagerProxy mStatsManagerProxy;
    private SystemMonitor mSystemMonitor;

    public CarTelemetryService(Context context, CarPropertyService carPropertyService) {
        mContext = context;
        mCarPropertyService = carPropertyService;
    }

    @Override
    public void init() {
        mTelemetryHandler.post(() -> {
            SystemInterface systemInterface = CarLocalServices.getService(SystemInterface.class);
            // full root directory path is /data/system/car/telemetry
            File rootDirectory = new File(systemInterface.getSystemCarDir(), TELEMETRY_DIR);
            // initialize all necessary components
            mMetricsConfigStore = new MetricsConfigStore(rootDirectory);
            mResultStore = new ResultStore(rootDirectory);
            mStatsManagerProxy = new StatsManagerImpl(
                    mContext.getSystemService(StatsManager.class));
            mPublisherFactory = new PublisherFactory(mCarPropertyService, mTelemetryHandler,
                    mStatsManagerProxy, rootDirectory);
            mDataBroker = new DataBrokerImpl(mContext, mPublisherFactory, mResultStore);
            mSystemMonitor = SystemMonitor.create(mContext, mTelemetryHandler);
            // controller starts metrics collection after boot complete
            mDataBrokerController = new DataBrokerController(mDataBroker, mTelemetryHandler,
                    mMetricsConfigStore, mSystemMonitor,
                    systemInterface.getSystemStateInterface());
        });
    }

    @Override
    public void release() {
        // TODO(b/197969149): prevent threading issue, block main thread
        mTelemetryHandler.post(() -> mResultStore.flushToDisk());
    }

    @Override
    public void dump(IndentingPrintWriter writer) {
        writer.println("Car Telemetry service");
    }

    /**
     * Registers a listener with CarTelemetryService for the service to send data to cloud app.
     */
    @Override
    public void setListener(@NonNull ICarTelemetryServiceListener listener) {
        // TODO(b/184890506): verify that only a hardcoded app can set the listener
        mContext.enforceCallingOrSelfPermission(
                Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
        mTelemetryHandler.post(() -> {
            if (DEBUG) {
                Slog.d(CarLog.TAG_TELEMETRY, "Setting the listener for car telemetry service");
            }
            mListener = listener;
        });
    }

    /**
     * Clears the listener registered with CarTelemetryService.
     */
    @Override
    public void clearListener() {
        mContext.enforceCallingOrSelfPermission(
                Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "clearListener");
        mTelemetryHandler.post(() -> {
            if (DEBUG) {
                Slog.d(CarLog.TAG_TELEMETRY, "Clearing the listener for car telemetry service");
            }
            mListener = null;
        });
    }

    /**
     * Send a telemetry metrics config to the service. This method assumes
     * {@link #setListener(ICarTelemetryServiceListener)} is called. Otherwise it does nothing.
     *
     * @param key    the unique key to identify the MetricsConfig.
     * @param config the serialized bytes of a MetricsConfig object.
     */
    @Override
    public void addMetricsConfig(@NonNull MetricsConfigKey key, @NonNull byte[] config) {
        mContext.enforceCallingOrSelfPermission(
                Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "addMetricsConfig");
        mTelemetryHandler.post(() -> {
            if (mListener == null) {
                Slog.w(CarLog.TAG_TELEMETRY, "ICarTelemetryServiceListener is not set");
                return;
            }
            Slog.d(CarLog.TAG_TELEMETRY, "Adding metrics config " + key.getName()
                    + " to car telemetry service");
            TelemetryProto.MetricsConfig metricsConfig = null;
            int status = ERROR_METRICS_CONFIG_UNKNOWN;
            try {
                metricsConfig = TelemetryProto.MetricsConfig.parseFrom(config);
            } catch (InvalidProtocolBufferException e) {
                Slog.e(CarLog.TAG_TELEMETRY, "Failed to parse MetricsConfig.", e);
                status = ERROR_METRICS_CONFIG_PARSE_FAILED;
            }
            // if config can be parsed, add it to persistent storage
            if (metricsConfig != null) {
                status = mMetricsConfigStore.addMetricsConfig(metricsConfig);
                // TODO(b/199410900): update logic once metrics configs have expiration dates
                mDataBroker.addMetricsConfiguration(metricsConfig);
            }
            // If no error (a config is successfully added), script results from an older version
            // should be deleted
            if (status == ERROR_METRICS_CONFIG_NONE) {
                mResultStore.removeResult(key.getName());
            }
            try {
                mListener.onAddMetricsConfigStatus(key, status);
            } catch (RemoteException e) {
                Slog.w(CarLog.TAG_TELEMETRY, "error with ICarTelemetryServiceListener", e);
            }
        });
    }

    /**
     * Removes a metrics config based on the key. This will also remove outputs produced by the
     * MetricsConfig.
     *
     * @param key the unique identifier of a MetricsConfig.
     */
    @Override
    public void removeMetricsConfig(@NonNull MetricsConfigKey key) {
        mContext.enforceCallingOrSelfPermission(
                Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "removeMetricsConfig");
        mTelemetryHandler.post(() -> {
            Slog.d(CarLog.TAG_TELEMETRY, "Removing metrics config " + key.getName()
                    + " from car telemetry service");
            // TODO(b/198792767): Check both config name and config version for removal
            mDataBroker.removeMetricsConfiguration(key.getName());
            mResultStore.removeResult(key.getName());
            mMetricsConfigStore.removeMetricsConfig(key.getName());
        });
    }

    /**
     * Removes all MetricsConfigs. This will also remove all MetricsConfig outputs.
     */
    @Override
    public void removeAllMetricsConfigs() {
        mContext.enforceCallingOrSelfPermission(
                Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "removeAllMetricsConfigs");
        mTelemetryHandler.post(() -> {
            Slog.d(CarLog.TAG_TELEMETRY,
                    "Removing all metrics config from car telemetry service");
            mDataBroker.removeAllMetricsConfigurations();
            mMetricsConfigStore.removeAllMetricsConfigs();
            mResultStore.removeAllResults();
        });
    }

    /**
     * Sends script results associated with the given key using the
     * {@link ICarTelemetryServiceListener}. This method assumes listener is set. Otherwise it
     * does nothing.
     *
     * @param key the unique identifier of a MetricsConfig.
     */
    @Override
    public void sendFinishedReports(@NonNull MetricsConfigKey key) {
        mContext.enforceCallingOrSelfPermission(
                Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "sendFinishedReports");
        mTelemetryHandler.post(() -> {
            if (mListener == null) {
                Slog.w(CarLog.TAG_TELEMETRY, "ICarTelemetryServiceListener is not set");
                return;
            }
            if (DEBUG) {
                Slog.d(CarLog.TAG_TELEMETRY,
                        "Flushing reports for metrics config " + key.getName());
            }
            PersistableBundle result = mResultStore.getFinalResult(key.getName(), true);
            TelemetryProto.TelemetryError error = mResultStore.getError(key.getName(), true);
            if (result != null) {
                sendFinalResult(key, result);
            } else if (error != null) {
                sendError(key, error);
            } else {
                Slog.w(CarLog.TAG_TELEMETRY, "config " + key.getName()
                        + " did not produce any results");
            }
        });
    }

    /**
     * Sends all script results or errors using the {@link ICarTelemetryServiceListener}.
     */
    @Override
    public void sendAllFinishedReports() {
        // TODO(b/184087869): Implement
        mContext.enforceCallingOrSelfPermission(
                Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "sendAllFinishedReports");
        if (DEBUG) {
            Slog.d(CarLog.TAG_TELEMETRY, "Flushing all reports");
        }
    }

    private void sendFinalResult(MetricsConfigKey key, PersistableBundle result) {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            result.writeToStream(bos);
            mListener.onResult(key, bos.toByteArray());
        } catch (RemoteException e) {
            Slog.w(CarLog.TAG_TELEMETRY, "error with ICarTelemetryServiceListener", e);
        } catch (IOException e) {
            Slog.w(CarLog.TAG_TELEMETRY, "failed to write bundle to output stream", e);
        }
    }

    private void sendError(MetricsConfigKey key, TelemetryProto.TelemetryError error) {
        try {
            mListener.onError(key, error.toByteArray());
        } catch (RemoteException e) {
            Slog.w(CarLog.TAG_TELEMETRY, "error with ICarTelemetryServiceListener", e);
        }
    }

    @VisibleForTesting
    Handler getTelemetryHandler() {
        return mTelemetryHandler;
    }

    @VisibleForTesting
    ResultStore getResultStore() {
        return mResultStore;
    }

    @VisibleForTesting
    MetricsConfigStore getMetricsConfigStore() {
        return mMetricsConfigStore;
    }
}
