// 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.Activity;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.util.Log;

import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import org.chromium.base.PathUtils;
import org.joda.time.Duration;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nullable;

import io.flutter.view.FlutterMain;
import io.flutter.view.FlutterView;
import io.v.android.VAndroidContext;
import io.v.android.VAndroidContexts;
import io.v.android.security.BlessingsManager;
import io.v.v23.options.RpcOptions;
import io.v.v23.security.Blessings;
import io.v.v23.vdl.ClientStream;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;
import java8.util.Maps;
import lombok.RequiredArgsConstructor;
import rx.Subscription;

/**
 * Activity representing the example 'app', a.k.a. the initiator/originator/master.
 */
public class DistroActivity extends Activity {
    private static final String TAG = DistroActivity.class.getSimpleName();
    private static final Duration PING_TIMEOUT = Duration.standardSeconds(3);
    private static final long POLL_INTERVAL = 750;

    private VAndroidContext context;
    private FlutterView flutterView;
    private final Map<String, ConnectionMonitor> clients = new HashMap<>();
    private ScheduledExecutorService poller;
    private Subscription subscription;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        poller = new ScheduledThreadPoolExecutor(1);

        FlutterMain.ensureInitializationComplete(getApplicationContext(), null);
        setContentView(R.layout.flutter_layout);

        flutterView = (FlutterView) findViewById(R.id.flutter_view);
        File appBundle = new File(PathUtils.getDataDirectory(this),
                FlutterMain.APP_BUNDLE);
        flutterView.runFromBundle(appBundle.getPath(), null);

        flutterView.sendToFlutter("runApp", "", r -> {
            context = VAndroidContexts.withDefaults(this, savedInstanceState);

            Futures.addCallback(BlessingsManager
                            .getBlessings(context.getVContext(), this, "blessings", true),
                    new FutureCallback<Blessings>() {
                        @Override
                        public void onSuccess(final Blessings blessings) {
                            onBlessingsAvailable(blessings);
                        }

                        @Override
                        public void onFailure(final Throwable t) {
                            Log.e(TAG, "Unable to attain blessings", t);
                        }
                    });
        });
    }

    private void onBlessingsAvailable(final Blessings blessings) {
        final Intent castIntent = new Intent(DistroActivity.this,
                DistroAndroidService.class);
        try {
            castIntent.putExtra(DistroAndroidService.BLESSINGS_EXTRA,
                    VomUtil.encodeToString(blessings, Blessings.class));
        } catch (final VException e) {
            Log.e(TAG, "Unable to encode blessings", e);
        }
        startService(castIntent);

        subscription = startScanning();

        flutterView.addOnMessageListener("initiateCast", this::initiateCast);
        flutterView.addOnMessageListener("updateCast", this::updateCast);
        flutterView.addOnMessageListener("terminateCast", this::terminateCast);
    }

    @Override
    protected void onDestroy() {
        if (subscription != null) {
            subscription.unsubscribe();
        }

        poller.shutdown();
        clients.clear();

        if (flutterView != null) {
            flutterView.destroy();
        }

        // TODO(rosswang): proactively signal cast termination; right now doing that intelligently
        // would necessitate keeping some extra state in the Java layer that's already in the
        // Flutter layer, so let's wait until the Flutter plug-in system is better fleshed out. For
        // now, we'll just wait for the (short) timeout.
        context.close();
        Log.i(TAG, "Closed Vanadium context");

        super.onDestroy();
    }

    @Override
    protected void onPause() {
        super.onPause();
        flutterView.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        flutterView.onResume();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        // Reload the Flutter Dart code when the activity receives an intent
        // from the "flutter refresh" command.
        // This feature should only be enabled during development.  Use the
        // debuggable flag as an indicator that we are in development mode.
        if ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            if (Intent.ACTION_RUN.equals(intent.getAction())) {
                flutterView.runFromBundle(intent.getDataString(),
                        intent.getStringExtra("snapshot"));
            }
        }
    }

    private boolean isActive() {
        return subscription != null && !subscription.isUnsubscribed();
    }

    private static abstract class TrappingCallback implements FutureCallback<Object> {
        @Override
        public void onSuccess(final @Nullable Object result) {
        }
    }

    private class ConnectionMonitor implements FutureCallback<String> {
        public final String name;
        private final DistroClient client;
        private ClientStream<State, State, Void> castStream;
        private ListenableFuture<String> poll;

        private final FutureCallback<Object> castTerminated = new FutureCallback<Object>() {
            private void notifyFlutter() {
                if (isActive()) {
                    flutterView.sendToFlutter("castTerminated", name);
                }
            }

            @Override
            public void onSuccess(final @Nullable Object result) {
                Log.i(TAG, "Cast terminated by " + name);
                notifyFlutter();
            }

            @Override
            public void onFailure(final Throwable t) {
                Log.i(TAG, "Cast terminated by " + name, t);
                notifyFlutter();
            }
        };

        private final TrappingCallback
                trapDeviceOffline = new TrappingCallback() {
                    @Override
                    public void onFailure(final Throwable t) {
                        Log.i(TAG, "Lost device " + name, t);

                        if (isActive()) {
                            flutterView.sendToFlutter("deviceOffline", name);
                            terminateCast();
                            clients.remove(name);
                        }
                    }
                },
                trapCastTerminated = new TrappingCallback() {
                    @Override
                    public void onFailure(final Throwable t) {
                        castTerminated.onFailure(t);
                    };
                };

        public ConnectionMonitor(final String name) {
            this.name = name;
            client = DistroClientFactory.getDistroClient(name);

            poll();
        }

        public void poll() {
            poll = client.getDescription(context.getVContext().withTimeout(PING_TIMEOUT));
            Futures.addCallback(poll, this);
        }

        @Override
        public void onSuccess(final String description) {
            if (isActive()) {
                final JSONObject message = new JSONObject();
                try {
                    message.put("name", name);
                    message.put("description", description);
                } catch (final JSONException wtf) {
                    throw new RuntimeException(wtf);
                }
                flutterView.sendToFlutter("deviceOnline", message.toString());

                poller.schedule(this::poll, POLL_INTERVAL, TimeUnit.MILLISECONDS);
            }
        }

        @Override
        public void onFailure(final Throwable t) {
            trapDeviceOffline.onFailure(t);
        }

        public ConnectionMonitor initiateCast() {
            castStream = client.cast(context.getVContext(), new RpcOptions()
                    .channelTimeout(DistroAndroidService.CHANNEL_TIMEOUT));
            Futures.addCallback(castStream.recv(), castTerminated);
            return this;
        }

        public void updateCast(final String data) {
            Futures.addCallback(castStream.send(new State(data)), trapCastTerminated);
        }

        public void terminateCast() {
            if (castStream != null) {
                Futures.addCallback(castStream.finish(), castTerminated);
                castStream = null;
            }
        }
    }

    private Subscription startScanning() {
        return Disco.scanContinuously(context)
                .subscribe(name -> Maps.computeIfAbsent(clients, name, ConnectionMonitor::new),
                        t -> context.getErrorReporter().onError(R.string.err_scan, t));
    }

    @RequiredArgsConstructor
    private static class CastMessage {
        public final String name, data;

        public static CastMessage fromJson(final String json) {
            final JSONObject message;
            try {
                message = new JSONObject(json);
                return new CastMessage(
                        message.getString("name"),
                        message.getString("data"));
            } catch (final JSONException e) {
                throw new IllegalArgumentException(e);
            }
        }
    }

    private String initiateCast(final String json) {
        final CastMessage message = CastMessage.fromJson(json);
        clients.get(message.name)
                .initiateCast()
                .updateCast(message.data);
        return null;
    }

    private String updateCast(final String json) {
        final CastMessage message = CastMessage.fromJson(json);
        clients.get(message.name)
                .updateCast(message.data);
        return null;
    }

    private String terminateCast(final String name) {
        final ConnectionMonitor conn = clients.get(name);
        if (conn != null) {
            conn.terminateCast();
        }

        return null;
    }
}
