// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.baku.examples.distro;

import android.app.Service;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.IBinder;
import android.provider.ContactsContract;
import android.support.annotation.Nullable;
import android.util.Log;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import com.jaredrummler.android.device.DeviceName;

import org.joda.time.Duration;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import io.v.android.v23.V;
import io.v.v23.context.VContext;
import io.v.v23.options.RpcServerOptions;
import io.v.v23.rpc.Server;
import io.v.v23.rpc.ServerCall;
import io.v.v23.security.BlessingPattern;
import io.v.v23.security.Blessings;
import io.v.v23.security.VPrincipal;
import io.v.v23.security.VSecurity;
import io.v.v23.vdl.ServerRecvStream;
import io.v.v23.vdl.ServerStream;
import io.v.v23.vdl.VdlAny;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;
import lombok.RequiredArgsConstructor;

public class DistroAndroidService extends Service {
    private static final String TAG = DistroAndroidService.class.getSimpleName();

    @RequiredArgsConstructor
    public static class Session {
        public final SettableFuture<Void> completion;
        public final ServerRecvStream<State> stream;
    }

    private static Map<String, Session> sessions = new HashMap<>();

    public static Session getSession(final String key) {
        return sessions.get(key);
    }

    public static final String
            BLESSINGS_EXTRA = "Blessings";

    public static final Duration CHANNEL_TIMEOUT = Duration.standardSeconds(3);

    private VContext vContext;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        vContext = V.init(this);

        final VPrincipal principal = V.getPrincipal(vContext);

        final Blessings blessings;
        try {
            blessings = (Blessings) VomUtil.decodeFromString(
                    intent.getStringExtra(BLESSINGS_EXTRA), Blessings.class);

            principal.blessingStore().setDefaultBlessings(blessings);
            principal.blessingStore().set(blessings, new BlessingPattern("..."));
            VSecurity.addToRoots(principal, blessings);
        } catch (final VException e) {
            // TODO(rosswang): handle this better
            Log.e(TAG, "Unable to assume blessings", e);
        }

        final DistroServer handlers = new DistroServer() {
            @Override
            public ListenableFuture<String> getDescription(final VContext context,
                                                           final ServerCall call) {
                final SettableFuture<String> description = SettableFuture.create();

                DeviceName.with(DistroAndroidService.this).request((i, e) -> {
                    final String owner;

                    final ContentResolver cr = getContentResolver();
                    try (final Cursor c = cr.query(Uri.withAppendedPath(
                            ContactsContract.Profile.CONTENT_URI,
                            ContactsContract.Contacts.Data.CONTENT_DIRECTORY),
                            null, null, null, null)) {

                        if (c.getCount() > 0) {
                            c.moveToFirst();
                            owner = c.getString(c.getColumnIndex(
                                    ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)) +
                                    "'s ";
                        } else {
                            owner = "";
                        }
                    }

                    final String device = e == null ? i.getName() : DeviceName.getDeviceName();
                    description.set(owner + device);
                });

                return description;
            }

            @Override
            public ListenableFuture<Void> cast(final VContext context, final ServerCall call,
                                               final ServerStream<VdlAny, State> stream) {
                final String key = UUID.randomUUID().toString();

                Log.i(TAG, "Hosting new casting session " + key);

                final SettableFuture<Void> completion = SettableFuture.create();
                completion.addListener(() -> {
                    sessions.remove(key);
                    Log.i(TAG, "Terminated casting session " + key);
                }, MoreExecutors.directExecutor());

                sessions.put(key, new Session(completion, stream));

                final Intent intent = new Intent(DistroAndroidService.this, HostActivity.class);
                intent.putExtra(HostActivity.SESSION_EXTRA, key);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                try {
                    startActivity(intent);
                } catch (final Exception e) {
                    completion.setException(e);
                    Log.e(TAG, e.getMessage(), e);
                }

                return completion;
            }
        };

        VContext listenContextCandidate;
        try {
            listenContextCandidate = V.withListenSpec(vContext,
                    V.getListenSpec(vContext).withProxy("proxy"));
        } catch (final VException e) {
            listenContextCandidate = vContext;
            Log.e(TAG, "Unable to listen on proxy", e);
        }

        final VContext listenContext = listenContextCandidate;

        final Server s;
        try {
            s = V.getServer(V.withNewServer(listenContext, Disco.name(this), handlers,
                    VSecurity.newAllowEveryoneAuthorizer(), new RpcServerOptions()
                            .channelTimeout(CHANNEL_TIMEOUT)));
        } catch (final VException e) {
            throw new RuntimeException(e);
        }

        return START_REDELIVER_INTENT;
    }

    @Override
    public void onDestroy() {
        vContext.cancel();
    }
}
