// Copyright 2015 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.android.apps.syncslides.db;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.joda.time.Duration;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

import io.v.android.apps.syncslides.R;
import io.v.android.apps.syncslides.misc.V23Manager;
import io.v.android.apps.syncslides.model.Deck;
import io.v.android.apps.syncslides.model.DeckFactory;
import io.v.android.apps.syncslides.model.Listener;
import io.v.android.apps.syncslides.model.NoopList;
import io.v.android.apps.syncslides.model.Slide;
import io.v.android.apps.syncslides.model.SlideImpl;
import io.v.android.v23.V;
import io.v.impl.google.naming.NamingUtil;
import io.v.impl.google.services.syncbase.SyncbaseServer;
import io.v.v23.context.CancelableVContext;
import io.v.v23.context.VContext;
import io.v.v23.rpc.Server;
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.nosql.SyncgroupMemberInfo;
import io.v.v23.services.syncbase.nosql.SyncgroupPrefix;
import io.v.v23.services.syncbase.nosql.SyncgroupSpec;
import io.v.v23.services.watch.ResumeMarker;
import io.v.v23.syncbase.Syncbase;
import io.v.v23.syncbase.SyncbaseApp;
import io.v.v23.syncbase.SyncbaseService;
import io.v.v23.syncbase.nosql.BatchDatabase;
import io.v.v23.syncbase.nosql.ChangeType;
import io.v.v23.syncbase.nosql.Database;
import io.v.v23.syncbase.nosql.DatabaseCore;
import io.v.v23.syncbase.nosql.RowRange;
import io.v.v23.syncbase.nosql.Stream;
import io.v.v23.syncbase.nosql.Syncgroup;
import io.v.v23.syncbase.nosql.Table;
import io.v.v23.syncbase.nosql.WatchChange;
import io.v.v23.vdl.VdlAny;
import io.v.v23.verror.Errors;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;

public class SyncbaseDB implements DB {

    private static final String TAG = "SyncbaseDB";
    private static final String SYNCBASE_APP = "syncslides";
    private static final String SYNCBASE_DB = "syncslides";
    private static final String DECKS_TABLE = "Decks";
    private static final String NOTES_TABLE = "Notes";
    static final String PRESENTATIONS_TABLE = "Presentations";
    static final String CURRENT_SLIDE = "CurrentSlide";
    static final String QUESTIONS = "questions";
    private static final String SYNCGROUP_PRESENTATION_DESCRIPTION = "Live Presentation";

    private boolean mInitialized = false;
    private Handler mHandler;
    private Permissions mPermissions;
    private Context mContext;
    private VContext mVContext;
    private Database mDB;
    private Table mDecks;
    private Table mNotes;
    private Table mPresentations;
    private final Map<String, CurrentSlideWatcher> mCurrentSlideWatchers;
    private final Map<String, QuestionWatcher> mQuestionWatchers;
    private Server mSyncbaseServer;
    private final DeckFactory mDeckFactory;

    SyncbaseDB(Context context) {
        mContext = context;
        mCurrentSlideWatchers = Maps.newHashMap();
        mQuestionWatchers = Maps.newHashMap();
        mDeckFactory = DeckFactory.Singleton.get(context);
    }

    @Override
    public void init(Activity activity) {
        Log.d(TAG, "init");
        if (mInitialized) {
            Log.d(TAG, "already initialized");
            return;
        }
        mHandler = new Handler(Looper.getMainLooper());
        // TODO(kash): Set proper ACLs.
        AccessList acl = new AccessList(
                ImmutableList.of(new BlessingPattern("...")), ImmutableList.<String>of());
        mPermissions = new Permissions(ImmutableMap.of(
                Constants.RESOLVE.getValue(), acl,
                Constants.READ.getValue(), acl,
                Constants.WRITE.getValue(), acl,
                Constants.ADMIN.getValue(), acl));

        // If blessings aren't in place, the fragment that called this
        // initialization may continue to load and use DB, but nothing will
        // work so DB methods should return noop values.  It's assumed that
        // the calling fragment will send the user to the AccountManager,
        // accept blessings on return, then re-call this init.
        if (!V23Manager.Singleton.get().isBlessed()) {
            Log.d(TAG, "no blessings.");
            return;
        }
        mVContext = V23Manager.Singleton.get().getVContext();
        setupSyncbase();
    }

    // TODO(kash): Run this in an AsyncTask so it doesn't block the UI.
    private void setupSyncbase() {
        // Prepare the syncbase storage directory.
        File storageDir = new File(mContext.getFilesDir(), "syncbase");
        storageDir.mkdirs();

        try {
            TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
            String id = tm.getDeviceId();
            if (id == null) {
                // NOTE(spetrovic): on a tablet, there is no TelephonyManager, so we try something
                // else.
                id = Settings.Secure.getString(
                        mContext.getContentResolver(), Settings.Secure.ANDROID_ID);
            }
            mVContext = SyncbaseServer.withNewServer(mVContext, new SyncbaseServer.Params()
                    .withPermissions(mPermissions)
                    .withName(V23Manager.syncName(id))
                    .withStorageRootDir(storageDir.getAbsolutePath()));
        } catch (SyncbaseServer.StartException e) {
            handleError("Couldn't start syncbase server");
            return;
        }
        try {
            mSyncbaseServer = V.getServer(mVContext);
            Log.i(TAG, "Endpoints: " + Arrays.toString(mSyncbaseServer.getStatus().getEndpoints()));
            String serverName = "/" + mSyncbaseServer.getStatus().getEndpoints()[0];
            SyncbaseService service = Syncbase.newService(serverName);
            SyncbaseApp app = service.getApp(SYNCBASE_APP);
            if (!app.exists(mVContext)) {
                app.create(mVContext, mPermissions);
            }
            mDB = app.getNoSqlDatabase(SYNCBASE_DB, null);
            if (!mDB.exists(mVContext)) {
                mDB.create(mVContext, mPermissions);
            }
            mDecks = mDB.getTable(DECKS_TABLE);
            if (!mDecks.exists(mVContext)) {
                mDecks.create(mVContext, mPermissions);
            }
            mNotes = mDB.getTable(NOTES_TABLE);
            if (!mNotes.exists(mVContext)) {
                mNotes.create(mVContext, mPermissions);
            }
            mPresentations = mDB.getTable(PRESENTATIONS_TABLE);
            if (!mPresentations.exists(mVContext)) {
                mPresentations.create(mVContext, mPermissions);
            }
            importDecks();
        } catch (VException e) {
            handleError("Couldn't setup syncbase service: " + e.getMessage());
            return;
        }
        mInitialized = true;
    }

    @Override
    public void createPresentation(final String deckId,
                                   final Callback<CreatePresentationResult> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                createPresentationRunnable(deckId, callback);
            }
        }).start();
    }

    private void createPresentationRunnable(final String deckId,
                                            final Callback<CreatePresentationResult> callback) {
        //final String presentationId = UUID.randomUUID().toString();
        final String presentationId = "randomPresentationId1";
        String prefix = NamingUtil.join(deckId, presentationId);
        try {
            // Add rows to Presentations table.
            VPresentation presentation = new VPresentation();  // Empty for now.
            mPresentations.put(mVContext, prefix, presentation, VPresentation.class);
            VCurrentSlide current = new VCurrentSlide(0);
            mPresentations.put(mVContext, NamingUtil.join(prefix, CURRENT_SLIDE),
                    current, VCurrentSlide.class);

            mPresentations.setPrefixPermissions(mVContext, RowRange.prefix(prefix),
                    mPermissions);
            mDecks.setPrefixPermissions(mVContext, RowRange.prefix(deckId), mPermissions);

            // Create the syncgroup.
            final String syncgroupName = NamingUtil.join(
                    mSyncbaseServer.getStatus().getMounts()[0].getName(),
                    "%%sync/syncslides",
                    prefix);
            //final String syncgroupName = STATIC_SYNCGROUP;
            Log.i(TAG, "Creating syncgroup " + syncgroupName);
            Syncgroup syncgroup = mDB.getSyncgroup(syncgroupName);
            CancelableVContext context = mVContext.withTimeout(Duration.millis(5000));
            try {
                syncgroup.create(
                        context,
                        new SyncgroupSpec(
                                SYNCGROUP_PRESENTATION_DESCRIPTION,
                                // TODO(kash): Use real permissions.
                                mPermissions,
                                Arrays.asList(
                                        new SyncgroupPrefix(PRESENTATIONS_TABLE, prefix),
                                        new SyncgroupPrefix(DECKS_TABLE, deckId)),
                                Arrays.asList(V23Manager.syncName("sg")),
                                false
                        ),
                        new SyncgroupMemberInfo((byte) 10));
            } catch (VException e) {
                if (e.is(Errors.EXIST)) {
                    Log.i(TAG, "Syncgroup already exists");
                } else {
                    throw e;
                }
            }
            Log.i(TAG, "Finished creating syncgroup");

            V23Manager.Singleton.get().scan("...");

            // TODO(kash): Create a syncgroup for Notes?  Not sure if we should do that
            // here or somewhere else.  We're not going to demo sync across a user's
            // devices right away, so we'll figure this out later.

            Handler handler = new Handler(Looper.getMainLooper());
            handler.post(new Runnable() {
                @Override
                public void run() {
                    callback.done(new CreatePresentationResult(presentationId, syncgroupName));
                }
            });
        } catch (VException e) {
            // TODO(kash): Change Callback to take an error parameter.
            handleError(e.toString());
            Handler handler = new Handler(Looper.getMainLooper());
            handler.post(new Runnable() {
                @Override
                public void run() {
                    // TODO(kash): fix me!
                    callback.done(new CreatePresentationResult(presentationId, "dummy name"));
                }
            });
        }
    }

    @Override
    public void joinPresentation(final String syncgroupName, final Callback<Void> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Log.i(TAG, "Joining: " + syncgroupName);
                    Syncgroup syncgroup = mDB.getSyncgroup(syncgroupName);
                    syncgroup.join(mVContext, new SyncgroupMemberInfo((byte) 1));
                    for (String member : syncgroup.getMembers(mVContext).keySet()) {
                        Log.i(TAG, "Member: " + member);
                    }
                    V23Manager.Singleton.get().scan("...");
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.done(null);
                        }
                    });
                } catch (VException e) {
                    handleError(e.toString());
                }
            }
        }).start();
    }

    @Override
    public DBList<Deck> getDecks() {
        if (!mInitialized) {
            return new NoopList<>();
        }
        return new DeckList(mVContext, mDB, mDeckFactory);
    }

    private static class DeckList implements DBList<Deck> {

        private final CancelableVContext mVContext;
        private final Database mDB;
        private final DeckFactory mDeckFactory;
        private final Handler mHandler;
        private ResumeMarker mWatchMarker;
        private boolean mIsDiscarded;
        private Listener mListener;
        private List<Deck> mDecks;

        public DeckList(VContext vContext, Database db, DeckFactory df) {
            mVContext = vContext.withCancel();
            mDB = db;
            mDeckFactory = df;
            mIsDiscarded = false;
            mDecks = Lists.newArrayList();
            mHandler = new Handler(Looper.getMainLooper());
            new Thread(new Runnable() {
                @Override
                public void run() {
                    fetchExistingDecks();
                }
            }).start();
        }

        private void fetchExistingDecks() {
            // TODO(kash): Uncomment this once we've figured out why performance is so bad.
            //Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            try {
                BatchDatabase batch = mDB.beginBatch(mVContext, null);
                mWatchMarker = batch.getResumeMarker(mVContext);
                DatabaseCore.ResultStream stream = batch.exec(mVContext,
                        "SELECT k, v FROM Decks WHERE Type(v) like \"%VDeck\"");
                for (List<VdlAny> row : stream) {
                    if (row.size() != 2) {
                        throw new VException("Wrong number of columns: " + row.size());
                    }
                    String key = (String) row.get(0).getElem();
                    Log.i(TAG, "Fetched deck " + key);
                    final Deck deck = mDeckFactory.make((VDeck) row.get(1).getElem(), key);
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            put(deck);
                        }
                    });
                }
                watchForDeckChanges();
            } catch (VException e) {
                Log.e(TAG, e.toString());
            }
        }

        private void watchForDeckChanges() {
            Stream<WatchChange> changeStream = null;
            try {
                changeStream = mDB.watch(mVContext, DECKS_TABLE, "", mWatchMarker);
            } catch (VException e) {
                Log.e(TAG, "Couldn't watch for changes to the Decks table: " + e.toString());
                return;
            }
            for (WatchChange change : changeStream) {
                if (!change.getTableName().equals(DECKS_TABLE)) {
                    Log.e(TAG, "Wrong change table name: " + change.getTableName() + ", wanted: " +
                            DECKS_TABLE);
                    continue;
                }
                final String key = change.getRowName();
                // Ignore slide changes.
                if (NamingUtil.split(key).size() != 1) {
                    Log.d(TAG, "Ignoring slide change: " + key);
                    continue;
                }
                Log.d(TAG, "Processing change to deck: " + key);
                if (change.getChangeType().equals(ChangeType.PUT_CHANGE)) {
                    // New deck or change to an existing deck.
                    VDeck vDeck = null;
                    try {
                        vDeck = (VDeck) VomUtil.decode(change.getVomValue(), VDeck.class);
                    } catch (VException e) {
                        Log.e(TAG, "Couldn't decode deck: " + e.toString());
                    }
                    final Deck deck = mDeckFactory.make(vDeck, key);
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            put(deck);
                        }
                    });
                } else {  // ChangeType.DELETE_CHANGE
                    // Existing deck deleted.
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            delete(key);
                        }
                    });
                }
            }
            Log.i(TAG, "Deck change thread exiting");
        }

        @Override
        public int getItemCount() {
            if (mDecks != null) {
                return mDecks.size();
            }
            return 0;
        }

        @Override
        public Deck get(int i) {
            if (mDecks != null) {
                return mDecks.get(i);
            }
            return null;
        }

        @Override
        public void setListener(Listener listener) {
            mListener = listener;
        }

        @Override
        public void discard() {
            Log.i(TAG, "Discarding deck list.");
            mIsDiscarded = true;
            mVContext.cancel();  // this will cause the watcher thread to exit
            mHandler.removeCallbacksAndMessages(null);
        }

        private void put(Deck deck) {
            // We need to check for mIsDiscarded (even though removeCallbacksAndMessages() has
            // been called), because that method doesn't prevent future post()s being made on
            // the handler.  So the following scenario is possible:
            //    - fetcher thread is about to execute post().
            //    - discard clears all pending messages from the handler.
            //    - fetcher executes the post().
            if (mIsDiscarded) {
                return;
            }
            // Keep the same sorted order as the Syncbase table, otherwise decks will shuffle
            // whenever we refresh them.
            int idx = 0;
            for (; idx < mDecks.size(); ++idx) {
                int comp = mDecks.get(idx).getId().compareTo(deck.getId());
                if (comp == 0) {
                    // Existing deck.
                    mDecks.set(idx, deck);
                    if (mListener != null) {
                        mListener.notifyItemChanged(idx);
                    }
                    return;
                } else if (comp > 0) {
                    break;
                }
            }
            // New deck.
            mDecks.add(idx, deck);
            if (mListener != null) {
                mListener.notifyItemInserted(idx);
            }
        }

        private void delete(String deckId) {
            // We need to check for mIsDiscarded (even though removeCallbacksAndMessages() has
            // been called), because that method doesn't prevent future post()s being made on
            // the handler.  So the following scenario is possible:
            //    - fetcher thread is about to execute post().
            //    - discard clears all pending messages from the handler.
            //    - fetcher executes the post().
            if (mIsDiscarded) {
                return;
            }
            for (int i = 0; i < mDecks.size(); ++i) {
                if (mDecks.get(i).getId().equals(deckId)) {
                    mDecks.remove(i);
                    if (mListener != null) {
                        mListener.notifyItemRemoved(i);
                    }
                    return;
                }
            }
        }
    }

    @Override
    public void getSlides(final String deckId, final Callback<List<Slide>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // We could probably share this block of code with SlideList.fetchData(),
                // but they are just different enough to make that annoying.  Not sure
                // that we'd really save anything in the end.
                try {
                    BatchDatabase batch = mDB.beginBatch(mVContext, null);
                    Table table = batch.getTable(NOTES_TABLE);

                    String query = "SELECT k, v FROM Decks WHERE Type(v) LIKE \"%VSlide\" " +
                            "AND k LIKE \"" + NamingUtil.join(deckId, "slides") + "%\"";
                    DatabaseCore.ResultStream stream = batch.exec(mVContext, query);
                    // TODO(kash): Abort execution if interrupted.  Perhaps we should derive
                    // a new VContext so it can be cancelled.
                    final List<Slide> slides = Lists.newArrayList();
                    for (List<VdlAny> row : stream) {
                        if (row.size() != 2) {
                            throw new VException("Wrong number of columns: " + row.size());
                        }
                        String key = (String) row.get(0).getElem();
                        Log.i(TAG, "Fetched slide " + key);
                        VSlide slide = (VSlide) row.get(1).getElem();
                        VNote note = (VNote) table.get(mVContext, key, VNote.class);
                        slides.add(new SlideImpl(
                                BitmapFactory.decodeByteArray(
                                        slide.getThumbnail(), 0, slide.getThumbnail().length),
                                note.getText()));
                    }
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.done(slides);
                        }
                    });
                } catch (VException e) {
                    Log.e(TAG, e.toString());
                }
            }
        }).start();
    }

    @Override
    public DBList<Slide> getSlides(String deckId) {
        if (!mInitialized) {
            return new NoopList<>();
        }
        return new SlideList(mVContext, mDB, deckId);
    }

    private static class SlideList implements DBList {
        private final CancelableVContext mVContext;
        private final Database mDB;
        private final Handler mHandler;
        private final String mDeckId;
        private ResumeMarker mWatchMarker;
        private boolean mIsDiscarded;
        // Storage for slides, mirroring the slides in the Syncbase.  Since slide numbers can
        // have "holes" in them (e.g., 1, 2, 4, 6, 8), we maintain a map from slide key
        // to the slide, as well as an ordered list which is returned to the caller.
        private TreeMap<String, Slide> mSlidesMap;
        private List<Slide> mSlides;
        private Listener mListener;

        public SlideList(VContext vContext, Database db, String deckId) {
            Log.i(TAG, "Fetching slides for " + deckId);
            mVContext = vContext.withCancel();
            mDB = db;
            mDeckId = deckId;
            mIsDiscarded = false;
            mSlidesMap = new TreeMap<>();
            mSlides = Lists.newArrayList();
            mHandler = new Handler(Looper.getMainLooper());
            new Thread(new Runnable() {
                @Override
                public void run() {
                    fetchExistingSlides();
                }
            }).start();
        }

        private void fetchExistingSlides() {
            // TODO(kash): Uncomment this once we've figured out why performance is so bad.
            //Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

            try {
                BatchDatabase batch = mDB.beginBatch(mVContext, null);
                mWatchMarker = batch.getResumeMarker(mVContext);
                Table notesTable = batch.getTable(NOTES_TABLE);

                String query = "SELECT k, v FROM Decks WHERE Type(v) LIKE \"%VSlide\" " +
                        "AND k LIKE \"" + NamingUtil.join(mDeckId, "slides") + "%\"";
                DatabaseCore.ResultStream stream = batch.exec(mVContext, query);
                for (List<VdlAny> row : stream) {
                    if (row.size() != 2) {
                        throw new VException("Wrong number of columns: " + row.size());
                    }
                    final String key = (String) row.get(0).getElem();
                    Log.i(TAG, "Fetched slide " + key);
                    VSlide slide = (VSlide) row.get(1).getElem();
                    String notes = notesForSlide(notesTable, key);
                    final SlideImpl newSlide = new SlideImpl(
                            BitmapFactory.decodeByteArray(
                                    slide.getThumbnail(), 0, slide.getThumbnail().length),
                            notes);
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            put(key, newSlide);
                        }
                    });
                }
                watchForSlideChanges();
            } catch (VException e) {
                Log.e(TAG, e.toString());
            }
        }

        private void watchForSlideChanges() {
            Table notesTable = mDB.getTable(NOTES_TABLE);
            Stream<WatchChange> changeStream;
            try {
                changeStream = mDB.watch(mVContext, DECKS_TABLE, "", mWatchMarker);
            } catch (VException e) {
                Log.e(TAG, "Couldn't watch for changes to the Decks table: " + e.toString());
                return;
            }

            for (WatchChange change : changeStream) {
                if (!change.getTableName().equals(DECKS_TABLE)) {
                    Log.e(TAG, "Wrong change table name: " + change.getTableName() + ", wanted: " +
                            DECKS_TABLE);
                    continue;
                }
                final String key = change.getRowName();
                // Ignore deck changes.
                if (NamingUtil.split(key).size() <= 1) {
                    Log.d(TAG, "Ignoring deck change: " + key);
                    continue;
                }
                if (change.getChangeType().equals(ChangeType.PUT_CHANGE)) {
                    // New slide or change to an existing slide.
                    VSlide vSlide = null;
                    try {
                        vSlide = (VSlide) VomUtil.decode(change.getVomValue(), VSlide.class);
                    } catch (VException e) {
                        Log.e(TAG, "Couldn't decode slide: " + e.toString());
                    }
                    String notes = notesForSlide(notesTable, key);
                    final SlideImpl slide = new SlideImpl(
                            BitmapFactory.decodeByteArray(
                                    vSlide.getThumbnail(), 0, vSlide.getThumbnail().length),
                            notes);
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            put(key, slide);
                        }
                    });
                } else {  // ChangeType.DELETE_CHANGE
                    // Existing slide deleted.
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            delete(key);
                        }
                    });
                }
            }
            Log.i(TAG, "Slides watcher thread exiting");
        }

        @Override
        public int getItemCount() {
            return mSlides.size();
        }

        @Override
        public Slide get(int i) {
            return mSlides.get(i);
        }

        @Override
        public void setListener(Listener listener) {
            mListener = listener;
        }

        @Override
        public void discard() {
            Log.i(TAG, "Discarding slides list");
            mIsDiscarded = true;
            mVContext.cancel();  // this will cause the watcher thread to exit
            mHandler.removeCallbacksAndMessages(null);
        }

        private void put(String key, Slide slide) {
            // We need to check for mIsDiscarded (even though removeCallbacksAndMessages() has
            // been called), because that method doesn't prevent future post()s being made on
            // the handler.  So the following scenario is possible:
            //    - fetcher thread is about to execute post().
            //    - discard clears all pending messages from the handler.
            //    - fetcher executes the post().
            if (mIsDiscarded) {
                return;
            }
            Slide oldSlide = mSlidesMap.put(key, slide);
            mSlides = Lists.newArrayList(mSlidesMap.values());
            int idx = mSlides.indexOf(slide);
            if (idx == -1) {
                // Should never happen.
                throw new RuntimeException("Can't find a newly inserted slide");
            }
            if (mListener != null) {
                if (oldSlide != null) {  // Update to an existing slide.
                    mListener.notifyItemChanged(idx);
                } else {
                    mListener.notifyItemInserted(idx);
                }
            }
        }

        private void delete(String key) {
            // We need to check for mIsDiscarded (even though removeCallbacksAndMessages() has
            // been called), because that method doesn't prevent future post()s being made on
            // the handler.  So the following scenario is possible:
            //    - fetcher thread is about to execute post().
            //    - discard clears all pending messages from the handler.
            //    - fetcher executes the post().
            if (mIsDiscarded) {
                return;
            }
            Slide deletedSlide = mSlidesMap.remove(key);
            if (deletedSlide == null) {
                Log.e(TAG, "Deleting a slide that doesn't exist: " + key);
                return;
            }
            int idx = mSlides.indexOf(deletedSlide);
            if (idx == -1) {
                // Should never happen.
                throw new RuntimeException("Couldn't find a deleted slide in the list");
            }
            mSlides.remove(idx);
            if (mListener != null) {
                mListener.notifyItemRemoved(idx);
            }
        }

        private String notesForSlide(Table notesTable, String key) {
            try {
                return ((VNote) notesTable.get(mVContext, key, VNote.class)).getText();
            } catch (VException e) {
                return "";
            }
        }
    }

    @Override
    public void setCurrentSlide(final String deckId, final String presentationId,
                                final int slideNum) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String rowKey = NamingUtil.join(deckId, presentationId, CURRENT_SLIDE);
                    Log.i(TAG, "Writing row " + rowKey + " with " + slideNum);
                    mPresentations.put(mVContext, rowKey, new VCurrentSlide(slideNum),
                            VCurrentSlide.class);
                } catch (VException e) {
                    handleError(e.toString());
                }
            }
        }).start();
    }

    @Override
    public void addCurrentSlideListener(String deckId, String presentationId,
                                        CurrentSlideListener listener) {
        String key = NamingUtil.join(deckId, presentationId);
        Log.i(TAG, "addCurrentSlideListener " + key);
        CurrentSlideWatcher watcher = mCurrentSlideWatchers.get(key);
        if (watcher == null) {
            watcher = new CurrentSlideWatcher(mVContext, mDB, deckId, presentationId);
            mCurrentSlideWatchers.put(key, watcher);
        }
        watcher.addListener(listener);
    }

    @Override
    public void removeCurrentSlideListener(String deckId, String presentationId,
                                           CurrentSlideListener listener) {
        String key = NamingUtil.join(deckId, presentationId);
        CurrentSlideWatcher watcher = mCurrentSlideWatchers.get(key);
        if (watcher == null) {
            return;
        }
        watcher.removeListener(listener);
        if (!watcher.hasListeners()) {
            mCurrentSlideWatchers.remove(key);
        }
    }

    @Override
    public void setQuestionListener(String deckId, String presentationId,
                                    QuestionListener listener) {
        String key = NamingUtil.join(deckId, presentationId);
        QuestionWatcher oldWatcher = mQuestionWatchers.get(key);
        if (oldWatcher != null) {
            oldWatcher.discard();
        }
        QuestionWatcher watcher = new QuestionWatcher(
                new WatcherState(mVContext, mDB, deckId, presentationId),
                listener);
        mQuestionWatchers.put(key, watcher);
    }

    @Override
    public void removeQuestionListener(String deckId, String presentationId, QuestionListener listener) {
        String key = NamingUtil.join(deckId, presentationId);
        QuestionWatcher oldWatcher = mQuestionWatchers.get(key);
        if (oldWatcher != null) {
            mQuestionWatchers.remove(oldWatcher);
            oldWatcher.discard();
        }
    }

    @Override
    public void askQuestion(final String deckId, final String presentationId,
                            final String firstName, final String lastName) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String rowKey = NamingUtil.join(deckId, presentationId, QUESTIONS,
                            UUID.randomUUID().toString());
                    Log.i(TAG, "Writing row " + rowKey + " with " + firstName + " " + lastName);
                    VQuestion question = new VQuestion(
                            new VPerson(firstName, lastName),
                            System.currentTimeMillis(),
                            false // Not yet answered.
                    );
                    mPresentations.put(mVContext, rowKey, question, VQuestion.class);
                    // TODO(kash): Set the ACL so nobody else can modify the question.
                } catch (VException e) {
                    handleError(e.toString());
                }
            }
        }).start();
    }

    private void handleError(String msg) {
        Log.e(TAG, msg);
        Toast.makeText(mContext, msg, Toast.LENGTH_LONG).show();
    }

    private void importDecks() {
        importDeckFromResources("deckId1", "Car Business", R.drawable.thumb_deck1);
        // These slow down app startup, so skip these for now.
//        importDeckFromResources("deckId2", "Baku Discovery", R.drawable.thumb_deck2);
//        importDeckFromResources("deckId3", "Vanadium", R.drawable.thumb_deck3);
    }

    private static final int[] SLIDEDRAWABLES = new int[]{
            R.drawable.slide1_thumb,
            R.drawable.slide2_thumb,
            R.drawable.slide3_thumb,
            R.drawable.slide4_thumb,
            R.drawable.slide5_thumb,
            R.drawable.slide6_thumb,
            R.drawable.slide7_thumb,
            R.drawable.slide8_thumb,
            R.drawable.slide9_thumb,
            R.drawable.slide10_thumb,
            R.drawable.slide11_thumb
    };

    private static final String[] SLIDENOTES = {
            "This is the teaser slide. It should be memorable and descriptive of what your " +
                    "company is trying to do", "",
            "The bigger the pain, the better",
            "How do you solve this problem? How is it better or different from existing solutions?",
            "Demo the product", "", "[REDACTED]",
            "They may have tractor traction, but we still have the competitive advantage",
            "I'm not a businessman. I'm a business, man", "There is no 'i' on this slide",
            "Sqrt(all evil)"};

    private void importDeckFromResources(String prefix, String title, int resourceId) {
        try {
            putDeck(prefix, title, getImageBytes(resourceId));
            for (int i = 0; i < SLIDENOTES.length; i++) {
                putSlide(prefix, i, getImageBytes(SLIDEDRAWABLES[i]), SLIDENOTES[i]);
            }
        } catch (VException e) {
            handleError(e.toString());
        }
    }

    @Override
    public void importDeck(io.v.android.apps.syncslides.model.Deck deck,
                           io.v.android.apps.syncslides.model.Slide[] slides) {
        try {
            putDeck(deck.getId(), deck.getTitle(), getImageBytes(deck.getThumb()));
            for (int i = 0; i < slides.length; ++i) {
                io.v.android.apps.syncslides.model.Slide slide = slides[i];
                putSlide(deck.getId(), i, getImageBytes(slide.getImage()), slide.getNotes());
            }
        } catch (VException e) {
            handleError(e.toString());
        }
    }

    @Override
    public void importDeck(final io.v.android.apps.syncslides.model.Deck deck,
                           final io.v.android.apps.syncslides.model.Slide[] slides,
                           final Callback<Void> callback) {
        new Thread() {
            @Override
            public void run() {
                importDeck(deck, slides);
                if (callback != null) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.done(null);
                        }
                    });
                }
            }
        }.start();
    }

    private void putDeck(String prefix, String title, byte[] thumbData) throws VException {
        Log.i(TAG, String.format("Adding deck %s, %s", prefix, title));
        if (!mDecks.getRow(prefix).exists(mVContext)) {
            mDecks.put(
                    mVContext,
                    prefix,
                    new VDeck(title, thumbData),
                    VDeck.class);
        }
    }

    private void putSlide(String prefix, int idx, byte[] thumbData, String note) throws VException {
        String key = NamingUtil.join(prefix, "slides", String.format("%04d", idx));
        Log.i(TAG, "Adding slide " + key);
        if (!mDecks.getRow(key).exists(mVContext)) {
            mDecks.put(
                    mVContext,
                    key,
                    new VSlide(thumbData),
                    VSlide.class);
        }
        Log.i(TAG, "Adding note: " + note);
        mNotes.put(mVContext, key, new VNote(note), VNote.class);
        mNotes.put(
                mVContext,
                NamingUtil.join(prefix, "LastViewed"),
                System.currentTimeMillis(),
                Long.class);
    }

    @Override
    public Deck getDeck(String deckId) {
        VDeck vDeck = null;
        try {
            vDeck = (VDeck) mDecks.get(mVContext, deckId, VDeck.class);
        } catch (VException e) {
            handleError(e.toString());
        }
        if (vDeck != null) {
            return mDeckFactory.make(vDeck, deckId);
        }
        return null;
    }

    @Override
    public void deleteDeck(String deckId) {
        try {
            mDecks.deleteRange(mVContext, RowRange.prefix(deckId));
        } catch (VException e) {
            handleError(e.toString());
        }
    }

    @Override
    public void deleteDeck(final String deckId, final Callback<Void> callback) {
        new Thread() {
            @Override
            public void run() {
                deleteDeck(deckId);
                if (callback != null) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.done(null);
                        }
                    });
                }
            }
        }.start();
    }

    private byte[] getImageBytes(int resourceId) {
        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), resourceId);
        return getImageBytes(bitmap);
    }

    private byte[] getImageBytes(Bitmap bitmap) {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 60, stream);
        return stream.toByteArray();
    }
}