// 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.syncslides.db;

import android.util.Log;

import java.util.List;

import io.v.impl.google.naming.NamingUtil;
import io.v.syncslides.model.Slide;
import io.v.syncslides.model.SlideImpl;
import io.v.v23.VIterable;
import io.v.v23.context.VContext;
import io.v.v23.services.watch.ResumeMarker;
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.Table;
import io.v.v23.syncbase.nosql.WatchChange;
import io.v.v23.vdl.VdlAny;
import io.v.v23.verror.NoExistException;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;

import static io.v.v23.VFutures.sync;

/**
 * Watches the slides in a single deck for changes.  Slides are sorted by their key.
 */
class SlideWatcher implements Watcher<Slide> {

    private static final String TAG = "SlideWatcher";
    private final Database mDb;
    private final String mDeckId;

    SlideWatcher(Database db, String deckId) {
        mDb = db;
        mDeckId = deckId;
    }

    @Override
    public void watch(VContext context, Listener<Slide> listener) {
        try {
            BatchDatabase batch = sync(mDb.beginBatch(context, null));
            ResumeMarker watchMarker = sync(batch.getResumeMarker(context));
            fetchInitialState(context, listener, batch);
            watchChanges(context, listener, watchMarker);
        } catch (VException e) {
            listener.onError(e);
        }
    }

    @Override
    public int compare(Slide lhs, Slide rhs) {
        return lhs.getId().compareTo(rhs.getId());
    }

    private void fetchInitialState(VContext context, Listener<Slide> listener,
                                   BatchDatabase batch) throws VException {
        Table notesTable = batch.getTable(SyncbaseDB.NOTES_TABLE);
        String query = "SELECT k, v FROM Decks WHERE Type(v) LIKE \"%VSlide\" " +
                "AND k LIKE \"" + NamingUtil.join(mDeckId, "slides") + "%\"";
        DatabaseCore.QueryResults results = sync(batch.exec(context, query));
        for (List<VdlAny> row : results) {
            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(context, notesTable, key);
            Slide newSlide = new DBSlide(key, slide, notes);
            listener.onPut(newSlide);
        }
    }

    private void watchChanges(VContext context, Listener<Slide> listener, ResumeMarker watchMarker)
            throws VException {
        Table notesTable = mDb.getTable(SyncbaseDB.NOTES_TABLE);
        VIterable<WatchChange> changes =
                sync(mDb.watch(context, SyncbaseDB.DECKS_TABLE, mDeckId, watchMarker));
        for (WatchChange change : changes) {
            String key = change.getRowName();
            if (isDeckKey(key)) {
                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());
                    continue; // Just skip it.
                }
                String notes = notesForSlide(context, notesTable, key);
                Slide newSlide = new DBSlide(key, vSlide, notes);
                listener.onPut(newSlide);
            } else { // ChangeType.DELETE_CHANGE
                listener.onDelete(new SlideImpl(key, null, null, null));
            }
        }
        if (changes.error() != null) {
            throw changes.error();
        }
    }

    /**
     * Returns true if {@code key} looks like a VDeck and not a VSlide.
     */
    private boolean isDeckKey(String key) {
        return NamingUtil.split(key).size() <= 1;
    }

    private static String notesForSlide(VContext context, Table notesTable, String key)
            throws VException {
        try {
            VNote note = (VNote) sync(notesTable.get(context, key, VNote.class));
            return note.getText();
        } catch (NoExistException e) {
            // It is ok for the notes to not exist for a slide.
            return "";
        }
    }
}
