// 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.v.todos.persistence.syncbase;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.annotation.NonNull;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.concurrent.Callable;

import io.v.impl.google.services.syncbase.SyncbaseServer;
import io.v.todos.model.ListSpec;
import io.v.todos.model.Task;
import io.v.todos.model.TaskSpec;
import io.v.todos.persistence.TodoListListener;
import io.v.todos.persistence.TodoListPersistence;
import io.v.todos.sharing.ShareListMenuFragment;
import io.v.v23.InputChannel;
import io.v.v23.InputChannelCallback;
import io.v.v23.InputChannels;
import io.v.v23.VFutures;
import io.v.v23.context.VContext;
import io.v.v23.security.BlessingPattern;
import io.v.v23.security.access.AccessList;
import io.v.v23.security.access.Constants;
import io.v.v23.security.access.Permissions;
import io.v.v23.services.syncbase.Id;
import io.v.v23.services.syncbase.SyncgroupSpec;
import io.v.v23.syncbase.ChangeType;
import io.v.v23.syncbase.Collection;
import io.v.v23.syncbase.Syncgroup;
import io.v.v23.syncbase.WatchChange;
import io.v.v23.verror.NoExistException;
import io.v.v23.verror.VException;

public class SyncbaseTodoList extends SyncbasePersistence implements TodoListPersistence {
    public static final String
            TAG = "SyncbaseTodoList",
            LIST_METADATA_ROW_NAME = "list",
            TASKS_PREFIX = "tasks_";

    private static final String
            SHOW_DONE_ROW_NAME = "ShowDone";

    private final Collection mList;
    private final TodoListListener mListener;
    private final IdGenerator mIdGenerator = new IdGenerator(IdAlphabets.ROW_NAME, true);
    private final Set<String> mTaskIds = new HashSet<>();
    private final Timer mMemberTimer;
    private ShareListMenuFragment mShareListMenuFragment;

    @Override
    protected void addFeatureFragments(FragmentManager manager, FragmentTransaction transaction) {
        super.addFeatureFragments(manager, transaction);
        if (transaction == null) {
            mShareListMenuFragment = ShareListMenuFragment.find(manager);
        } else {
            mShareListMenuFragment = new ShareListMenuFragment();
            transaction.add(mShareListMenuFragment, ShareListMenuFragment.FRAGMENT_TAG);
        }
        mShareListMenuFragment.persistence = this;
        mShareListMenuFragment.setEmail(getPersonalEmail());
        // TODO(alexfandrianto): I shouldn't show the sharing menu item when this person cannot
        // share the todo list with other people. (Cannot re-share in this app.)
    }

    /**
     * This assumes that the collection for this list already exists.
     */
    public SyncbaseTodoList(Activity activity, Bundle savedInstanceState, String listId,
                            TodoListListener listener)
            throws VException, SyncbaseServer.StartException {
        super(activity, savedInstanceState);
        mListener = listener;

        mList = getDatabase().getCollection(getVContext(), listId);
        InputChannel<WatchChange> listWatch = getDatabase().watch(getVContext(), mList.id(), "");
        ListenableFuture<Void> listWatchFuture = InputChannels.withCallback(listWatch,
                new InputChannelCallback<WatchChange>() {
                    @Override
                    public ListenableFuture<Void> onNext(WatchChange change) {
                        processWatchChange(change);
                        return null;
                    }
                });
        Futures.addCallback(listWatchFuture, new SyncTrappingCallback<Void>() {
            @Override
            public void onFailure(@NonNull Throwable t) {
                if (t instanceof NoExistException) {
                    // The collection has been deleted.
                    mListener.onDelete();
                } else {
                    super.onFailure(t);
                }
            }
        });

        mMemberTimer = watchSharedTo(listId, new Function<List<BlessingPattern>, Void>() {
            @Override
            public Void apply(List<BlessingPattern> patterns) {
                // Analyze these patterns to construct the emails, and fire the listener!
                List<String> emails = parseEmailsFromPatterns(patterns);
                mShareListMenuFragment.setSharedTo(emails);
                return null;
            }
        });

        // Watch the "showDone" boolean in the userdata collection and forward changes to the
        // listener.
        InputChannel<WatchChange> showDoneWatch = getDatabase()
                .watch(getVContext(), getUserCollection().id(), SHOW_DONE_ROW_NAME);
        trap(InputChannels.withCallback(showDoneWatch, new InputChannelCallback<WatchChange>() {
            @Override
            public ListenableFuture<Void> onNext(WatchChange result) {
                mListener.onUpdateShowDone((boolean) result.getValue());
                return null;
            }
        }));
    }

    protected List<String> parseEmailsFromPatterns(List<BlessingPattern> patterns) {
        List<String> emails = new ArrayList<>();

        for (BlessingPattern pattern : patterns) {
            if (pattern.isMatchedBy(CLOUD_BLESSING)) {
                // Skip. It's the cloud, and that doesn't count.
                continue;
            }
            if (pattern.toString().endsWith(getPersonalEmail())) {
                // Skip. It's you, and that doesn't count.
                continue;
            }
            emails.add(getEmailFromPattern(pattern));
        }
        return emails;
    }

    @Override
    public void close() {
        mMemberTimer.cancel();
        super.close();
    }

    private void processWatchChange(WatchChange change) {
        String rowName = change.getRowName();

        if (rowName.equals(SyncbaseTodoList.LIST_METADATA_ROW_NAME)) {
            ListSpec listSpec = SyncbasePersistence.castFromSyncbase(change.getValue(),
                    ListSpec.class);
            mListener.onUpdate(listSpec);
        } else if (change.getChangeType() == ChangeType.DELETE_CHANGE) {
            mTaskIds.remove(rowName);
            mListener.onItemDelete(rowName);
        } else {
            mIdGenerator.registerId(change.getRowName().substring(TASKS_PREFIX.length()));

            TaskSpec taskSpec = SyncbasePersistence.castFromSyncbase(change.getValue(),
                    TaskSpec.class);
            Task task = new Task(rowName, taskSpec);

            if (mTaskIds.add(rowName)) {
                mListener.onItemAdd(task);
            } else {
                mListener.onItemUpdate(task);
            }
        }
    }

    @Override
    public void updateTodoList(ListSpec listSpec) {
        trap(mList.put(getVContext(), LIST_METADATA_ROW_NAME, listSpec, ListSpec.class));
    }

    @Override
    public void deleteTodoList() {
        trap(getUserCollection().delete(getVContext(), mList.id().getName()));
        trap(mList.destroy(getVContext()));
    }

    private Syncgroup getListSyncgroup() {
        return getDatabase().getSyncgroup(new Id(getPersonalBlessingsString(),
                computeListSyncgroupName(mList.id().getName())));
    }

    @Override
    public void shareTodoList(final Iterable<String> emails) {
        // Get the syncgroup
        final Syncgroup sgHandle = getListSyncgroup();

        // Get the Syncgroup Spec and add read access. Then get the collection permissions and add
        // both read and write access. Along the way, trigger the listener's onShareChanged.

        trap(sExecutor.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                Map<String, SyncgroupSpec> specMap = VFutures.sync(sgHandle.getSpec(getVContext()));

                String version = Iterables.getOnlyElement(specMap.keySet());
                SyncgroupSpec spec = specMap.get(version);

                // Modify the syncgroup spec to update the permissions.
                Permissions perms = spec.getPerms();
                addPermissions(perms, emails, Constants.READ.getValue());
                VFutures.sync(sgHandle.setSpec(getVContext(), spec, version));

                // TODO(alexfandrianto): This should be the right place to send the invite
                // explicitly to the selected emails.

                // Analyze these patterns to construct the emails, and fire the listener!
                List<String> specEmails = parseEmailsFromPatterns(
                        perms.get(Constants.READ.getValue()).getIn());
                mShareListMenuFragment.setSharedTo(specEmails);

                // Add read and write access to the collection permissions.
                perms = VFutures.sync(mList.getPermissions(getVContext()));

                addPermissions(perms, emails, Constants.READ.getValue());
                addPermissions(perms, emails, Constants.WRITE.getValue());
                VFutures.sync(mList.setPermissions(getVContext(), perms));
                return null;
            }
        }));
    }

    // TODO(alexfandrianto): We should consider moving this helper into the main Java repo.
    // https://github.com/vanadium/issues/issues/1321
    // TODO(alexfandrianto): This allows you to repeatedly add the same blessings to the permission
    // multiple times.
    private static void addPermissions(Permissions perms, Iterable<String> emails, String tag) {
        AccessList acl = perms.get(tag);
        List<BlessingPattern> patterns = acl.getIn();
        for (String email : emails) {
            patterns.add(new BlessingPattern(blessingsStringFromEmail(email)));
        }
        perms.put(tag, acl);
    }

    public static ListenableFuture<Void> updateListTimestamp(final VContext vContext,
                                                             final Collection list) {
        ListenableFuture<Object> get = list.get(vContext, LIST_METADATA_ROW_NAME, ListSpec.class);
        return Futures.transformAsync(get, new AsyncFunction<Object, Void>() {
            @Override
            public ListenableFuture<Void> apply(Object oldValue) throws Exception {
                ListSpec listSpec = (ListSpec) oldValue;
                listSpec.setUpdatedAt(System.currentTimeMillis());
                return list.put(vContext, LIST_METADATA_ROW_NAME, listSpec, ListSpec.class);
            }
        });
    }

    private void updateListTimestamp() {
        trap(updateListTimestamp(getVContext(), mList));
    }

    @Override
    public void addTask(TaskSpec task) {
        trap(mList.put(getVContext(), TASKS_PREFIX + mIdGenerator.generateTailId(), task,
                TaskSpec.class));
        updateListTimestamp();
    }

    @Override
    public void updateTask(Task task) {
        trap(mList.put(getVContext(), task.key, task.toSpec(), TaskSpec.class));
        updateListTimestamp();
    }

    @Override
    public void deleteTask(String key) {
        trap(mList.delete(getVContext(), key));
        updateListTimestamp();
    }

    @Override
    public void setShowDone(boolean showDone) {
        trap(getUserCollection().put(getVContext(), SHOW_DONE_ROW_NAME, showDone, Boolean.TYPE));
    }
}
