/// The goal of log writer is to generically manage game logs.
/// Syncbase will produce values that combine to form a List<GameCommand> while
/// the in-memory GameLog will also hold such a list.
///
/// Updating the GameLog from the Store/Syncbase:
/// GameLog will update to whatever Store data says.
/// If it merges, the game log, then it will write that information off.
/// Case A: Store is farther along than current state.
/// Continue.
/// Case B: Store is somehow behind the current state.
/// Update with the current state of the GameLog (if not sent yet).
/// Case C: Store's log branches off from the curernt GameLog.
/// Depending on phase, resolve the conflict differently and write the resolution.
///
/// Updating the Store:
/// When a new GameCommand is received (that doesn't contradict the existing log),
/// it is added to a list of pending changes and written to the local store.

/// Since this file includes Sky/Mojo, it will need to be mocked out for unit tests.
/// Unfortunately, imports can't be replaced, so the best thing to do is to swap out the whole file.

import 'dart:async';
import 'dart:convert' show UTF8, JSON;

import 'package:sky/mojo/embedder.dart' show embedder;

import 'package:ether/syncbase_client.dart'
    show Perms, SyncbaseClient, SyncbaseTable;

log(String msg) {
  DateTime now = new DateTime.now();
  print('$now $msg');
}

Perms emptyPerms() => new Perms()..json = '{}';

class LogWriter {
  final Function updateCallback; // Takes in Map<String, String> data
  final SyncbaseClient _syncbaseClient;

  LogWriter(this.updateCallback) :
    _syncbaseClient = new SyncbaseClient(embedder.connectToService,
        'https://mojo.v.io/syncbase_server.mojo');

  int seq = 0;
  SyncbaseTable tb;
  String sendMsg, recvMsg, putStr, getStr;

  Future _doSyncbaseInit() async {
    log('LogWriter.doSyncbaseInit');
    if (tb != null) {
      log('syncbase already initialized');
      return;
    }
    var app = _syncbaseClient.app('app');
    if (!(await app.exists())) {
      await app.create(emptyPerms());
    }
    var db = app.noSqlDatabase('db');
    if (!(await db.exists())) {
      await db.create(emptyPerms());
    }
    var table = db.table('table');
    if (!(await table.exists())) {
      await table.create(emptyPerms());
    }
    tb = table;
    log('syncbase is now initialized');

    // TODO(alexfandrianto): I'm not sure how we setup 'watch', but we would do so here.
  }

  Future write(Map<String, String> data) async {
    log('LogWriter.write start');
    await _doSyncbaseInit();

    var row = tb.row('key');
    await row.put(UTF8.encode(JSON.encode(data)));

    // TODO(alexfandrianto): Normally, we would watch, but since I don't know how, I will just poll here.
    await _poll();
    log('LogWriter.start done');
  }

  Future _poll() async {
    log('LogWriter.poll start');
    await _doSyncbaseInit();

    // Realistically, we wouldn't write it all to a single row, but I don't think it matters right now.
    var row = tb.row('key');
    var getBytes = await row.get();

    Map<String, String> data = JSON.decode(UTF8.decode(getBytes));
    this.updateCallback(data);
    log('LogWriter.poll done');
  }
}
