/*
 * Copyright (C) 2017 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 android.car.diagnostic;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.car.Car;
import android.car.CarApiUtil;
import android.car.CarLibLog;
import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
import android.car.diagnostic.ICarDiagnosticEventListener.Stub;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;

import com.android.car.internal.CarPermission;
import com.android.car.internal.CarRatedListeners;
import com.android.car.internal.SingleMessageHandler;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * API for monitoring car diagnostic data.
 *
 * @hide
 */
@SystemApi
public final class CarDiagnosticManager implements CarManagerBase {
    public static final int FRAME_TYPE_LIVE = 0;
    public static final int FRAME_TYPE_FREEZE = 1;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({FRAME_TYPE_LIVE, FRAME_TYPE_FREEZE})
    /** @hide */
    public @interface FrameType {}

    /** @hide */
    public static final @FrameType int FRAME_TYPES[] = {
        FRAME_TYPE_LIVE,
        FRAME_TYPE_FREEZE
    };

    private static final int MSG_DIAGNOSTIC_EVENTS = 0;

    private final ICarDiagnostic mService;
    private final SparseArray<CarDiagnosticListeners> mActiveListeners = new SparseArray<>();

    /** Handles call back into clients. */
    private final SingleMessageHandler<CarDiagnosticEvent> mHandlerCallback;

    private CarDiagnosticEventListenerToService mListenerToService;

    private final CarPermission mVendorExtensionPermission;

    /** @hide */
    public CarDiagnosticManager(IBinder service, Context context, Handler handler) {
        mService = ICarDiagnostic.Stub.asInterface(service);
        mHandlerCallback = new SingleMessageHandler<CarDiagnosticEvent>(handler.getLooper(),
            MSG_DIAGNOSTIC_EVENTS) {
            @Override
            protected void handleEvent(CarDiagnosticEvent event) {
                CarDiagnosticListeners listeners;
                synchronized (mActiveListeners) {
                    listeners = mActiveListeners.get(event.frameType);
                }
                if (listeners != null) {
                    listeners.onDiagnosticEvent(event);
                }
            }
        };
        mVendorExtensionPermission = new CarPermission(context, Car.PERMISSION_VENDOR_EXTENSION);
    }

    @Override
    /** @hide */
    public void onCarDisconnected() {
        synchronized(mActiveListeners) {
            mActiveListeners.clear();
            mListenerToService = null;
        }
    }

    /** Listener for diagnostic events. Callbacks are called in the Looper context. */
    public interface OnDiagnosticEventListener {
        /**
         * Called when there is a diagnostic event from the car.
         *
         * @param carDiagnosticEvent
         */
        void onDiagnosticEvent(final CarDiagnosticEvent carDiagnosticEvent);
    }

    // OnDiagnosticEventListener registration

    private void assertFrameType(@FrameType int frameType) {
        switch(frameType) {
            case FRAME_TYPE_FREEZE:
            case FRAME_TYPE_LIVE:
                return;
            default:
                throw new IllegalArgumentException(String.format(
                            "%d is not a valid diagnostic frame type", frameType));
        }
    }

    /**
     * Register a new listener for events of a given frame type and rate.
     * @param listener
     * @param frameType
     * @param rate
     * @return true if the registration was successful; false otherwise
     * @throws CarNotConnectedException
     * @throws IllegalArgumentException
     */
    public boolean registerListener(OnDiagnosticEventListener listener,
            @FrameType int frameType,
            int rate)
                throws CarNotConnectedException, IllegalArgumentException {
        assertFrameType(frameType);
        synchronized(mActiveListeners) {
            if (null == mListenerToService) {
                mListenerToService = new CarDiagnosticEventListenerToService(this);
            }
            boolean needsServerUpdate = false;
            CarDiagnosticListeners listeners = mActiveListeners.get(frameType);
            if (listeners == null) {
                listeners = new CarDiagnosticListeners(rate);
                mActiveListeners.put(frameType, listeners);
                needsServerUpdate = true;
            }
            if (listeners.addAndUpdateRate(listener, rate)) {
                needsServerUpdate = true;
            }
            if (needsServerUpdate) {
                if (!registerOrUpdateDiagnosticListener(frameType, rate)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Unregister a listener, causing it to stop receiving all diagnostic events.
     * @param listener
     */
    public void unregisterListener(OnDiagnosticEventListener listener) {
        synchronized(mActiveListeners) {
            for(@FrameType int frameType : FRAME_TYPES) {
                doUnregisterListenerLocked(listener, frameType);
            }
        }
    }

    private void doUnregisterListenerLocked(OnDiagnosticEventListener listener,
            @FrameType int frameType) {
        CarDiagnosticListeners listeners = mActiveListeners.get(frameType);
        if (listeners != null) {
            boolean needsServerUpdate = false;
            if (listeners.contains(listener)) {
                needsServerUpdate = listeners.remove(listener);
            }
            if (listeners.isEmpty()) {
                try {
                    mService.unregisterDiagnosticListener(frameType,
                        mListenerToService);
                } catch (RemoteException e) {
                    //ignore
                }
                mActiveListeners.remove(frameType);
            } else if (needsServerUpdate) {
                try {
                    registerOrUpdateDiagnosticListener(frameType, listeners.getRate());
                } catch (CarNotConnectedException e) {
                    // ignore
                }
            }
        }
    }

    private boolean registerOrUpdateDiagnosticListener(@FrameType int frameType, int rate)
        throws CarNotConnectedException {
        try {
            return mService.registerOrUpdateDiagnosticListener(frameType, rate, mListenerToService);
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return false;
    }

    // ICarDiagnostic forwards

    /**
     * Retrieve the most-recently acquired live frame data from the car.
     * @return A CarDiagnostic event for the most recently known live frame if one is present.
     *         null if no live frame has been recorded by the vehicle.
     * @throws CarNotConnectedException
     */
    public @Nullable
    CarDiagnosticEvent getLatestLiveFrame() throws CarNotConnectedException {
        try {
            return mService.getLatestLiveFrame();
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return null;
    }

    /**
     * Return the list of the timestamps for which a freeze frame is currently stored.
     * @return An array containing timestamps at which, at the current time, the vehicle has
     *         a freeze frame stored. If no freeze frames are currently stored, an empty
     *         array will be returned.
     * Because vehicles might have a limited amount of storage for frames, clients cannot
     * assume that a timestamp obtained via this call will be indefinitely valid for retrieval
     * of the actual diagnostic data, and must be prepared to handle a missing frame.
     * @throws CarNotConnectedException
     */
    public long[] getFreezeFrameTimestamps() throws CarNotConnectedException {
        try {
            return mService.getFreezeFrameTimestamps();
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return new long[]{};
    }

    /**
     * Retrieve the freeze frame event data for a given timestamp, if available.
     * @param timestamp
     * @return A CarDiagnostic event for the frame at the given timestamp, if one is
     *         available. null is returned otherwise.
     * Storage constraints might cause frames to be deleted from vehicle memory.
     * For this reason it cannot be assumed that a timestamp will yield a valid frame,
     * even if it was initially obtained via a call to getFreezeFrameTimestamps().
     * @throws CarNotConnectedException
     */
    public @Nullable
    CarDiagnosticEvent getFreezeFrame(long timestamp)
        throws CarNotConnectedException {
        try {
            return mService.getFreezeFrame(timestamp);
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return null;
    }

    /**
     * Clear the freeze frame information from vehicle memory at the given timestamps.
     * @param timestamps A list of timestamps to delete freeze frames at, or an empty array
     *                   to delete all freeze frames from vehicle memory.
     * @return true if all the required frames were deleted (including if no timestamps are
     *         provided and all frames were cleared); false otherwise.
     * Due to storage constraints, timestamps cannot be assumed to be indefinitely valid, and
     * a false return from this method should be used by the client as cause for invalidating
     * its local knowledge of the vehicle diagnostic state.
     * @throws CarNotConnectedException
     */
    public boolean clearFreezeFrames(long... timestamps) throws CarNotConnectedException {
        try {
            return mService.clearFreezeFrames(timestamps);
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return false;
    }

    /**
     * Returns true if this vehicle supports sending live frame information.
     * @return
     * @throws CarNotConnectedException
     */
    public boolean isLiveFrameSupported() throws CarNotConnectedException {
        try {
            return mService.isLiveFrameSupported();
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return false;
    }

    /**
     * Returns true if this vehicle supports supports sending notifications to
     * registered listeners when new freeze frames happen.
     * @throws CarNotConnectedException
     */
    public boolean isFreezeFrameNotificationSupported() throws CarNotConnectedException {
        try {
            return mService.isFreezeFrameNotificationSupported();
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return false;
    }

    /**
     * Returns whether the underlying HAL supports retrieving freeze frames
     * stored in vehicle memory using timestamp.
     * @throws CarNotConnectedException
     */
    public boolean isGetFreezeFrameSupported() throws CarNotConnectedException {
        try {
            return mService.isGetFreezeFrameSupported();
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return false;
    }

    /**
     * Returns true if this vehicle supports clearing all freeze frames.
     * This is only meaningful if freeze frame data is also supported.
     *
     * A return value of true for this method indicates that it is supported to call
     * carDiagnosticManager.clearFreezeFrames()
     * to delete all freeze frames stored in vehicle memory.
     *
     * @return
     * @throws CarNotConnectedException
     */
    public boolean isClearFreezeFramesSupported() throws CarNotConnectedException {
        try {
            return mService.isClearFreezeFramesSupported();
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return false;
    }

    /**
     * Returns true if this vehicle supports clearing specific freeze frames by timestamp.
     * This is only meaningful if freeze frame data is also supported.
     *
     * A return value of true for this method indicates that it is supported to call
     * carDiagnosticManager.clearFreezeFrames(timestamp1, timestamp2, ...)
     * to delete the freeze frames stored for the provided input timestamps, provided any exist.
     *
     * @return
     * @throws CarNotConnectedException
     */
    public boolean isSelectiveClearFreezeFramesSupported() throws CarNotConnectedException {
        try {
            return mService.isSelectiveClearFreezeFramesSupported();
        } catch (IllegalStateException e) {
            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
        } catch (RemoteException e) {
            throw new CarNotConnectedException();
        }
        return false;
    }

    private static class CarDiagnosticEventListenerToService
            extends Stub {
        private final WeakReference<CarDiagnosticManager> mManager;

        public CarDiagnosticEventListenerToService(CarDiagnosticManager manager) {
            mManager = new WeakReference<>(manager);
        }

        private void handleOnDiagnosticEvents(CarDiagnosticManager manager,
            List<CarDiagnosticEvent> events) {
            manager.mHandlerCallback.sendEvents(events);
        }

        @Override
        public void onDiagnosticEvents(List<CarDiagnosticEvent> events) {
            CarDiagnosticManager manager = mManager.get();
            if (manager != null) {
                handleOnDiagnosticEvents(manager, events);
            }
        }
    }

    private class CarDiagnosticListeners extends CarRatedListeners<OnDiagnosticEventListener> {
        CarDiagnosticListeners(int rate) {
            super(rate);
        }

        void onDiagnosticEvent(final CarDiagnosticEvent event) {
            // throw away old data as oneway binder call can change order.
            long updateTime = event.timestamp;
            if (updateTime < mLastUpdateTime) {
                Log.w(CarLibLog.TAG_DIAGNOSTIC, "dropping old data");
                return;
            }
            mLastUpdateTime = updateTime;
            final boolean hasVendorExtensionPermission = mVendorExtensionPermission.checkGranted();
            final CarDiagnosticEvent eventToDispatch = hasVendorExtensionPermission ?
                    event :
                    event.withVendorSensorsRemoved();
            List<OnDiagnosticEventListener> listeners;
            synchronized (mActiveListeners) {
                listeners = new ArrayList<>(getListeners());
            }
            listeners.forEach(new Consumer<OnDiagnosticEventListener>() {

                @Override
                public void accept(OnDiagnosticEventListener listener) {
                    listener.onDiagnosticEvent(eventToDispatch);
                }
            });
        }
    }
}
