export const create = page => new RISE(page);

class RISE {

  constructor(page) {
    this.page = page;
  }

  getName() {
    return 'RISE';
  }

  isActive() {
    return this.page.evaluate(_ => typeof Jupyter !== 'undefined' && typeof Jupyter.notebook !== 'undefined');
  }

  async configure() {
    // wait until the RISE extension has loaded
    await this.page.waitForSelector('#RISE', { timeout: 30000 });
    // then start the slideshow if not already
    await this.page.evaluate(_ => {
      // check if slideshow has already started with autolaunch option
      if (!$('#maintoolbar').hasClass('reveal_tagging')) {
        // click on the 'Enter/Exit RISE Slideshow' button in the notebook toolbar
        $('#RISE').click();
      }
      // remove help an exit buttons
      $('#help_b, #exit_b').fadeToggle();
    });
    // then wait until Reveal.js gets configured by the RISE extension
    await this.page.waitForFunction('typeof Reveal !== \'undefined\' && Reveal.isReady()', { timeout: 30000 });
    // finally override Reveal.js configuration
    await this.page.evaluate(_ => Reveal.configure({
      controls    : false,
      progress    : false,
      slideNumber : false,
      // TODO: provide an option to turn fragments off
      fragments   : true,
    }));
  }

  slideCount() {
    // TODO: the getTotalSlides API does not report the number of slides accurately
    // as it does not take stacks and some index-less fragments into account
    // getTotalSlides API is only available starting reveal.js version 3.0.0
    return this.page.evaluate(_ => typeof Reveal.getTotalSlides === 'function'
      ? Reveal.getTotalSlides()
      : undefined);
  }

  hasNextSlide() {
    return this.page.evaluate(_ => !Reveal.isLastSlide() || Reveal.availableFragments().next);
  }

  nextSlide() {
    return this.page.evaluate(_ => Reveal.next());
  }

  currentSlideIndex() {
    return this.page.evaluate(_ => {
      const indices = Reveal.getIndices();
      const id = Reveal.getCurrentSlide().getAttribute('id');
      return typeof id === 'string' && id.length
        ? '/' + id
        : '/' + indices.h + (indices.v > 0 ? '/' + indices.v : '');
    });
  }
}
