/*
 * Copyright (C) 2014 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.location.provider;

import com.android.internal.util.Preconditions;

import android.hardware.location.IActivityRecognitionHardware;
import android.hardware.location.IActivityRecognitionHardwareSink;
import android.os.RemoteException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

/**
 * A class that exposes {@link IActivityRecognitionHardware} functionality to unbundled services.
 */
public final class ActivityRecognitionProvider {
    private final IActivityRecognitionHardware mService;
    private final HashSet<Sink> mSinkSet = new HashSet<Sink>();
    private final SinkTransport mSinkTransport = new SinkTransport();

    // the following constants must remain in sync with activity_recognition.h

    public static final String ACTIVITY_IN_VEHICLE = "android.activity_recognition.in_vehicle";
    public static final String ACTIVITY_ON_BICYCLE = "android.activity_recognition.on_bicycle";
    public static final String ACTIVITY_WALKING = "android.activity_recognition.walking";
    public static final String ACTIVITY_RUNNING = "android.activity_recognition.running";
    public static final String ACTIVITY_STILL = "android.activity_recognition.still";
    public static final String ACTIVITY_TILTING = "android.activity_recognition.tilting";

    public static final int EVENT_TYPE_FLUSH_COMPLETE = 0;
    public static final int EVENT_TYPE_ENTER = 1;
    public static final int EVENT_TYPE_EXIT = 2;

    // end constants activity_recognition.h

    /**
     * Used to receive Activity-Recognition events.
     */
    public interface Sink {
        void onActivityChanged(ActivityChangedEvent event);
    }

    public ActivityRecognitionProvider(IActivityRecognitionHardware service)
            throws RemoteException {
        Preconditions.checkNotNull(service);
        mService = service;
        mService.registerSink(mSinkTransport);
    }

    public String[] getSupportedActivities() throws RemoteException {
        return mService.getSupportedActivities();
    }

    public boolean isActivitySupported(String activity) throws RemoteException {
        return mService.isActivitySupported(activity);
    }

    public void registerSink(Sink sink) {
        Preconditions.checkNotNull(sink);
        synchronized (mSinkSet) {
            mSinkSet.add(sink);
        }
    }

    // TODO: if this functionality is exposed to 3rd party developers, handle unregistration (here
    // and in the service) of all sinks while failing to disable all events
    public void unregisterSink(Sink sink) {
        Preconditions.checkNotNull(sink);
        synchronized (mSinkSet) {
            mSinkSet.remove(sink);
        }
    }

    public boolean enableActivityEvent(String activity, int eventType, long reportLatencyNs)
            throws RemoteException {
        return mService.enableActivityEvent(activity, eventType, reportLatencyNs);
    }

    public boolean disableActivityEvent(String activity, int eventType) throws RemoteException {
        return mService.disableActivityEvent(activity, eventType);
    }

    public boolean flush() throws RemoteException {
        return mService.flush();
    }

    private final class SinkTransport extends IActivityRecognitionHardwareSink.Stub {
        @Override
        public void onActivityChanged(
                android.hardware.location.ActivityChangedEvent activityChangedEvent) {
            Collection<Sink> sinks;
            synchronized (mSinkSet) {
                if (mSinkSet.isEmpty()) {
                    return;
                }

                sinks = new ArrayList<Sink>(mSinkSet);
            }

            // translate the event from platform internal and GmsCore types
            ArrayList<ActivityRecognitionEvent> gmsEvents =
                    new ArrayList<ActivityRecognitionEvent>();
            for (android.hardware.location.ActivityRecognitionEvent event
                    : activityChangedEvent.getActivityRecognitionEvents()) {
                ActivityRecognitionEvent gmsEvent = new ActivityRecognitionEvent(
                        event.getActivity(),
                        event.getEventType(),
                        event.getTimestampNs());
                gmsEvents.add(gmsEvent);
            }
            ActivityChangedEvent gmsEvent = new ActivityChangedEvent(gmsEvents);

            for (Sink sink : sinks) {
                sink.onActivityChanged(gmsEvent);
            }
        }
    }
}
