// 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.

part of syncbase_store;

class _AppActions extends AppActions {
  _AppState _state;
  Function _emitChange;
  _AppActions(this._state, this._emitChange);

  //////////////////////////////////////
  // Decks

  Future addDeck(model.Deck deck) async {
    log.info("Adding deck ${deck.name}...");
    sb.SyncbaseTable tb = _getDecksTable();
    await tb.put(deck.key, UTF8.encode(deck.toJson()));
    log.info("Deck ${deck.name} added.");
  }

  Future removeDeck(String deckKey) async {
    sb.SyncbaseTable tb = _getDecksTable();
    tb.deleteRange(new sb.RowRange.prefix(deckKey));
  }

  Future setSlides(String deckKey, List<model.Slide> slides) async {
    sb.SyncbaseTable tb = _getDecksTable();

    slides.forEach((slide) async {
      // TODO(aghassemi): Use batching.
      await tb.put(
          keyutil.getSlideKey(deckKey, slide.num), UTF8.encode(slide.toJson()));
    });
  }

  Future setCurrSlideNum(String deckId, int slideNum) async {
    var deckState = _state._getOrCreateDeckState(deckId);
    if (slideNum < 0 || slideNum >= deckState.slides.length) {
      throw new ArgumentError.value(slideNum,
          "Slide number out of range. Only ${deckState.slides.length} slides exist.");
    }

    // TODO(aghassemi): Have a session table to persist UI state such as
    // local slide number within a deck, whether user is navigating a presentation
    // on their own, and similar UI state that is desirable to be persisted.
    deckState._currSlideNum = slideNum;

    // Is slide number change happening within a presentation?
    if (deckState.presentation != null) {
      // Is the current user driving the presentation?
      if (deckState.presentation.isDriving(_state.user)) {
        // Update the common slide number for the presentation.
        sb.SyncbaseTable tb = _getPresentationsTable();
        await tb.put(
            keyutil.getPresentationCurrSlideNumKey(
                deckId, deckState.presentation.key),
            UTF8.encode(slideNum.toString()));
      } else {
        // User is not driving the presentation so they are navigating on their own.
        deckState.presentation._isFollowingPresentation = false;
      }
    }
    _emitChange();
  }

  Future loadDeckFromSdCard() {
    return new Loader.singleton().loadDeck();
  }

  //////////////////////////////////////
  // Presentation

  Future<model.PresentationAdvertisement> startPresentation(
      String deckId) async {
    var alreadyAdvertised = _state._advertisedPresentations
        .any((model.PresentationAdvertisement p) => p.deck.key == deckId);
    if (alreadyAdvertised) {
      throw new ArgumentError.value(deckId,
          'Cannot simultaneously present the same deck. Presentation already in progress.');
    }

    if (!_state._decks.containsKey(deckId)) {
      throw new ArgumentError.value(deckId, 'Deck no longer exists.');
    }

    model.Deck deck = _state._getOrCreateDeckState(deckId)._deck;
    String presentationId = uuidutil.createUuid();
    String syncgroupName = _getSyncgroupName(_state.settings, presentationId);
    String thumbnailSyncgroupName =
        _getSyncgroupName(_state.settings, deck.thumbnail.key);

    var presentation = new model.PresentationAdvertisement(
        presentationId, deck, syncgroupName, thumbnailSyncgroupName);

    // Syncgroup for deck and presentation data, including blobs.
    await sb.createSyncgroup(_state.settings.mounttable, syncgroupName, [
      sb.SyncbaseClient.syncgroupPrefix(decksTableName, deckId),
      sb.SyncbaseClient.syncgroupPrefix(presentationsTableName,
          keyutil.getPresentationPrefix(deckId, presentationId)),
      sb.SyncbaseClient.syncgroupPrefix(blobsTableName, deckId)
    ]);

    // TODO(aghassemi): Use a simple RPC instead of a syncgroup to get the thumbnail.
    // See https://github.com/vanadium/syncslides/issues/17
    // Syncgroup for deck thumbnail.
    await sb.createSyncgroup(
        _state.settings.mounttable, thumbnailSyncgroupName, [
      sb.SyncbaseClient.syncgroupPrefix(blobsTableName, deck.thumbnail.key)
    ]);

    await discovery.advertise(presentation);
    _state._advertisedPresentations.add(presentation);

    // Set the presentation state for the deck.
    _DeckState deckState = _state._getOrCreateDeckState(deckId);
    _PresentationState presentationstate =
        deckState._getOrCreatePresentationState(presentation.key);
    presentationstate._isOwner = true;

    setDefaultsAndJoin() async {
      // Set the current slide number to 0.
      sb.SyncbaseTable tb = _getPresentationsTable();
      await tb.put(
          keyutil.getPresentationCurrSlideNumKey(deckId, presentation.key),
          UTF8.encode('0'));

      // Set the current user as the driver.
      await _setPresentationDriver(deckId, presentation.key, _state.user);

      // Also join the presentation.
      await joinPresentation(presentation);
    }

    try {
      // Wait for join. If it fails, remove the presentation state from the deck.
      await setDefaultsAndJoin();
    } catch (e) {
      deckState._isPresenting = false;
      throw e;
    }

    return presentation;
  }

  Future joinPresentation(model.PresentationAdvertisement presentation) async {
    String deckId = presentation.deck.key;

    // Set the presentation state for the deck.
    _DeckState deckState = _state._getOrCreateDeckState(deckId);
    deckState._getOrCreatePresentationState(presentation.key);

    deckState._isPresenting = true;

    // Wait until at least the current slide number, driver and the slide for current slide number is synced.
    join() async {
      bool isMyOwnPresentation =
          _state._advertisedPresentations.any((p) => p.key == presentation.key);
      if (!isMyOwnPresentation) {
        await sb.joinSyncgroup(presentation.syncgroupName);
      }

      Completer completer = new Completer();
      new Timer.periodic(new Duration(milliseconds: 30), (Timer timer) {
        if (_state._decks.containsKey(deckId) &&
            _state._decks[deckId].deck != null &&
            _state._decks[deckId].presentation != null &&
            _state._decks[deckId].slides.length >
                _state._decks[deckId].presentation.currSlideNum &&
            _state._decks[deckId].presentation.driver != null &&
            !completer.isCompleted) {
          timer.cancel();
          completer.complete();
        }
      });
      await completer.future.timeout(new Duration(seconds: 20));
    }

    try {
      // Wait for join. If it fails, remove the presentation state from the deck.
      await join();
    } catch (e) {
      deckState._isPresenting = false;
      throw e;
    }

    log.info('Joined presentation ${presentation.key}');
  }

  Future stopPresentation(String presentationId) async {
    await discovery.stopAdvertising(presentationId);
    _state._advertisedPresentations.removeWhere((p) => p.key == presentationId);
    _state._decks.values.forEach((_DeckState deck) {
      if (deck.presentation != null &&
          deck.presentation.key == presentationId) {
        deck._isPresenting = false;
      }
    });
    _emitChange();
    log.info('Presentation $presentationId stopped');
  }

  Future followPresentation(String deckId) async {
    var deckState = _state._getOrCreateDeckState(deckId);

    if (deckState.presentation == null) {
      throw new ArgumentError.value(deckId, 'Deck is not being presented.');
    }

    // Set the current slide number to the presentation's current slide number.
    await setCurrSlideNum(deckId, deckState.presentation.currSlideNum);

    deckState.presentation._isFollowingPresentation = true;
  }

  Future askQuestion(String deckId, int slideNum, String questionText) async {
    var deckState = _state._getOrCreateDeckState(deckId);

    if (deckState.presentation == null) {
      throw new ArgumentError.value(deckId,
          'Cannot ask a question because deck is not part of a presentation');
    }

    sb.SyncbaseTable tb = _getPresentationsTable();
    String questionId = uuidutil.createUuid();

    model.Question question = new model.Question(
        questionId, questionText, slideNum, _state.user, new DateTime.now());

    var key = keyutil.getPresentationQuestionKey(
        deckId, deckState.presentation.key, questionId);

    await tb.put(key, UTF8.encode(question.toJson()));
  }

  Future setDriver(String deckId, model.User driver) async {
    var deckState = _state._getOrCreateDeckState(deckId);

    if (deckState.presentation == null) {
      throw new ArgumentError.value(deckId,
          'Cannot set the driver because deck is not part of a presentation');
    }
    await _setPresentationDriver(deckId, deckState.presentation.key, driver);
  }

  //////////////////////////////////////
  // Blobs

  Future putBlob(String key, List<int> bytes) async {
    sb.SyncbaseTable tb = _getBlobsTable();
    await tb.put(key, bytes);
  }

  Future<List<int>> getBlob(String key) async {
    sb.SyncbaseTable tb = _getBlobsTable();
    return tb.get(key);
  }
}

//////////////////////////////////////
// Utilities

Future _setPresentationDriver(
    String deckId, String presentationId, model.User driver) async {
  sb.SyncbaseTable tb = _getPresentationsTable();
  await tb.put(keyutil.getPresentationDriverKey(deckId, presentationId),
      UTF8.encode(driver.toJson()));
}

String _getSyncgroupName(model.Settings settings, String uuid) {
  return '${settings.mounttable}/${settings.deviceId}/%%sync/$uuid';
}

sb.SyncbaseTable _getDecksTable() {
  return sb.database.table(decksTableName);
}

sb.SyncbaseTable _getPresentationsTable() {
  return sb.database.table(presentationsTableName);
}

sb.SyncbaseTable _getBlobsTable() {
  return sb.database.table(blobsTableName);
}
