// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. 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 swarmlib;

// TODO(jacobr): there is a lot of dead code in this class. Checking is as is
// and then doing a large pass to remove functionality that doesn't make sense
// given the UI layout.

/// Front page of Swarm.
// TODO(jacobr): this code now needs a large refactoring.
// Suggested refactorings:
//  Move animation specific code into helper classes.
class FrontView extends CompositeView {
  final Swarm swarm;

  /// View containing all UI anchored to the top of the page. */
  CompositeView topView;

  /// View containing all UI anchored to the left side of the page. */
  CompositeView bottomView;
  HeaderView headerView;
  late final SliderMenu sliderMenu;

  /// When the user is viewing a story, the data source for that story is
  /// detached from the section and shown at the bottom of the screen. This keeps
  /// track of that so we can restore it later.
  DataSourceView? detachedView;

  /// Map from section title to the View that shows this section.  This
  /// is populated lazily.
  StoryContentView? storyView;
  bool nextPrevShown;

  ConveyorView sections;

  /// The set of keys that produce a given behavior (going down one story,
  /// navigating to the column to the right, etc).
  //TODO(jmesserly): we need a key code enumeration
  final Set downKeyPresses;
  final Set upKeyPresses;
  final Set rightKeyPresses;
  final Set leftKeyPresses;
  final Set openKeyPresses;
  final Set backKeyPresses;
  final Set nextPageKeyPresses;
  final Set previousPageKeyPresses;

  FrontView(this.swarm)
    : downKeyPresses = {74 /*j*/, 40 /*down*/},
      upKeyPresses = {75 /*k*/, 38 /*up*/},
      rightKeyPresses = {39 /*right*/, 68 /*d*/, 76 /*l*/},
      leftKeyPresses = {37 /*left*/, 65 /*a*/, 72 /*h*/},
      openKeyPresses = {13 /*enter*/, 79 /*o*/},
      backKeyPresses = {8 /*delete*/, 27 /*escape*/},
      nextPageKeyPresses = {78 /*n*/},
      previousPageKeyPresses = {80 /*p*/},
      nextPrevShown = false,
      topView = CompositeView('top-view', false, false, false),
      headerView = HeaderView(swarm),
      bottomView = CompositeView('bottom-view', false, false, false),
      sections = ConveyorView(),
      super('front-view fullpage') {
    topView.addChild(headerView);

    sliderMenu = SliderMenu(swarm.sections.sectionTitles, (sectionTitle) {
      swarm.state.moveToNewSection(sectionTitle);
      _onSectionSelected(sectionTitle);
      // Start with no articles selected.
      swarm.state.selectedArticle.value = null;
    });
    topView.addChild(sliderMenu);
    addChild(topView);
    addChild(bottomView);
    sections.viewSelected = _onSectionTransitionEnded;
  }

  SectionView get currentSection {
    var view = sections.selectedView;
    // TODO(jmesserly): this code works around a bug in the DartC --optimize
    if (view == null) {
      view = sections.childViews[0];
      sections.selectView(view);
    }
    return view as SectionView;
  }

  @override
  void afterRender(Element node) {
    _createSectionViews();
    attachWatch(swarm.state.currentArticle, (e) {
      _refreshCurrentArticle();
    });
    attachWatch(swarm.state.storyMaximized, (e) {
      _refreshMaximized();
    });
  }

  void _refreshCurrentArticle() {
    if (!swarm.state.inMainView) {
      _animateToStory(swarm.state.currentArticle.value!);
    } else {
      _animateToMainView();
    }
  }

  /// Animates back from the story view to the main grid view.
  void _animateToMainView() {
    sliderMenu.removeClass('hidden');
    storyView!.addClass('hidden-story');
    currentSection.storyMode = false;

    headerView.startTransitionToMainView();

    currentSection.dataSourceView!.reattachSubview(
      detachedView!.source,
      detachedView!,
      true,
    );

    storyView!.node.onTransitionEnd.first.then((e) {
      currentSection.hidden = false;
      // TODO(rnystrom): Should move this "mode" into SwarmState and have
      // header view respond to change events itself.
      removeChild(storyView!);
      storyView = null;
      detachedView!.removeClass('sel');
      detachedView = null;
    });
  }

  void _animateToStory(Article item) {
    final source = item.dataSource;

    if (detachedView != null && detachedView!.source != source) {
      // Ignore spurious item selection clicks that occur while a data source
      // is already selected.  These are likely clicks that occur while an
      // animation is in progress.
      return;
    }

    if (storyView != null) {
      // Remove the old story. This happens if we're already in the Story View
      // and the user has clicked to see a new story.
      removeChild(storyView!);

      // Create the new story view and place in the frame.
      storyView = addChild(StoryContentView(swarm, item));
    } else {
      // We are animating from the main view to the story view.
      // TODO(jmesserly): make this code better
      final view = currentSection.findView(source);

      final newPosition = FxUtil.computeRelativePosition(
        view.node,
        bottomView.node,
      );
      currentSection.dataSourceView!.detachSubview(view.source);
      detachedView = view;

      FxUtil.setPosition(view.node, newPosition);
      bottomView.addChild(view);
      view.addClass('sel');
      currentSection.storyMode = true;

      // Create the new story view.
      storyView = StoryContentView(swarm, item);
      Timer(const Duration(milliseconds: 0), () {
        _animateDataSourceToMinimized();

        sliderMenu.addClass('hidden');
        // Make the fancy sliding into the window animation.
        Timer(const Duration(milliseconds: 0), () {
          storyView!.addClass('hidden-story');
          addChild(storyView!);
          Timer(const Duration(milliseconds: 0), () {
            storyView!.removeClass('hidden-story');
          });
          headerView.endTransitionToStoryView();
        });
      });
    }
  }

  void _refreshMaximized() {
    if (swarm.state.storyMaximized.value) {
      _animateDataSourceToMaximized();
    } else {
      _animateDataSourceToMinimized();
    }
  }

  void _animateDataSourceToMaximized() {
    FxUtil.setWebkitTransform(topView.node, 0, -HeaderView.HEIGHT);
    if (detachedView != null) {
      FxUtil.setWebkitTransform(
        detachedView!.node,
        0,
        -DataSourceView.TAB_ONLY_HEIGHT,
      );
    }
  }

  void _animateDataSourceToMinimized() {
    if (detachedView != null) {
      FxUtil.setWebkitTransform(detachedView!.node, 0, 0);
      FxUtil.setWebkitTransform(topView.node, 0, 0);
    }
  }

  /// Called when the animation to switch to a section has completed.
  void _onSectionTransitionEnded(SectionView selectedView) {
    // Show the section and hide the others.
    for (View view in sections.childViews) {
      if ((view as SectionView) == selectedView) {
        // Always refresh the sources in case they've changed.
        view.showSources();
      } else {
        // Only show the current view for performance.
        view.hideSources();
      }
    }
  }

  /// Called when the user chooses a section on the SliderMenu.  Hides
  /// all views except the one they want to see.
  void _onSectionSelected(String sectionTitle) {
    final section = swarm.sections.findSection(sectionTitle);
    // Find the view for this section.
    for (View view in sections.childViews) {
      if ((view as SectionView).section == section) {
        // Have the conveyor show it.
        sections.selectView(view);
        break;
      }
    }
  }

  /// Create SectionViews for each Section in the app and add them to the
  /// conveyor. Note that the SectionViews won't actually populate or load data
  /// sources until they are shown in response to [:_onSectionSelected():].
  void _createSectionViews() {
    for (final section in swarm.sections) {
      final viewFactory = DataSourceViewFactory(swarm);
      final sectionView = SectionView(swarm, section, viewFactory);

      // TODO(rnystrom): Hack temp. Access node to make sure SectionView has
      // rendered and created scroller. This can go away when event registration
      // is being deferred.
      sectionView.node;

      sections.addChild(sectionView);
    }
    addChild(sections);
  }

  /// Controls the logic of how to respond to keypresses and then update the
  /// UI accordingly.
  void processKeyEvent(KeyboardEvent e) {
    int code = e.keyCode;
    if (swarm.state.inMainView) {
      // Option 1: We're in the Main Grid mode.
      if (!swarm.state.hasArticleSelected) {
        // Then a key has been pressed. Select the first item in the
        // top left corner.
        swarm.state.goToFirstArticleInSection();
      } else if (rightKeyPresses.contains(code)) {
        // Store original state that is needed if we need to move
        // to the next section.
        swarm.state.goToNextFeed();
      } else if (leftKeyPresses.contains(code)) {
        // Store original state that is needed if we need to move
        // to the next section.
        swarm.state.goToPreviousFeed();
      } else if (downKeyPresses.contains(code)) {
        swarm.state.goToNextSelectedArticle();
      } else if (upKeyPresses.contains(code)) {
        swarm.state.goToPreviousSelectedArticle();
      } else if (openKeyPresses.contains(code)) {
        // View a story in the larger Story View.
        swarm.state.selectStoryAsCurrent();
      } else if (nextPageKeyPresses.contains(code)) {
        swarm.state.goToNextSection(sliderMenu);
      } else if (previousPageKeyPresses.contains(code)) {
        swarm.state.goToPreviousSection(sliderMenu);
      }
    } else {
      // Option 2: We're in Story Mode. In this mode, the user can move up
      // and down through stories, which automatically loads the next story.
      if (downKeyPresses.contains(code)) {
        swarm.state.goToNextArticle();
      } else if (upKeyPresses.contains(code)) {
        swarm.state.goToPreviousArticle();
      } else if (backKeyPresses.contains(code)) {
        // Move back to the main grid view.
        swarm.state.clearCurrentArticle();
      }
    }
  }
}

/// Transitions the app back to the main screen. */
void _backToMain(SwarmState state) {
  if (state.currentArticle.value != null) {
    state.clearCurrentArticle();
    state.storyTextMode.value = true;
    state.pushToHistory();
  }
}

/// A back button that sends the user back to the front page. */
class SwarmBackButton extends View {
  Swarm swarm;

  SwarmBackButton(this.swarm);

  @override
  Element render() => Element.html('<div class="back-arrow button"></div>');

  @override
  void afterRender(Element node) {
    addOnClick((e) {
      _backToMain(swarm.state);
    });
  }
}

/// Top view constaining the title and standard buttons. */
class HeaderView extends CompositeView {
  // TODO(jacobr): make this value be coupled with the CSS file.
  static const HEIGHT = 80;
  Swarm swarm;

  late final View _title;
  late final View _infoButton;
  late final View _configButton;
  late final View _refreshButton;
  late final SwarmBackButton _backButton;
  View? _infoDialog;
  View? _configDialog;

  // For (text/web) article view controls
  late final View _webBackButton;
  late final View _webForwardButton;
  late final View _newWindowButton;

  HeaderView(this.swarm) : super('header-view') {
    _backButton = addChild(SwarmBackButton(swarm));
    _title = addChild(View.div('app-title', 'Swarm'));
    _configButton = addChild(View.div('config button'));
    _refreshButton = addChild(View.div('refresh button'));
    _infoButton = addChild(View.div('info-button button'));

    // TODO(rnystrom): No more web/text mode (it's just text) so get rid of
    // these.
    _webBackButton = addChild(WebBackButton());
    _webForwardButton = addChild(WebForwardButton());
    _newWindowButton = addChild(View.div('new-window-button button'));
  }

  @override
  void afterRender(Element node) {
    // Respond to changes to whether the story is being shown as text or web.
    attachWatch(swarm.state.storyTextMode, (e) {
      refreshWebStoryButtons();
    });

    _title.addOnClick((e) {
      _backToMain(swarm.state);
    });

    // Wire up the events.
    _configButton.addOnClick((e) {
      // Bring up the config dialog.
      if (_configDialog == null) {
        // TODO(terry): Cleanup, HeaderView shouldn't be tangled with main view.
        _configDialog = ConfigHintDialog(swarm.frontView, () {
          swarm.frontView.removeChild(_configDialog!);
          _configDialog = null;

          // TODO: Need to push these to the server on a per-user basis.
          // Update the storage now.
          swarm.sections.refresh();
        });

        swarm.frontView.addChild(_configDialog!);
      }
      // TODO(jimhug): Graceful redirection to reader.
    });

    // On click of the refresh button, refresh the swarm.
    _refreshButton.addOnClick(
      EventBatch.wrap((e) {
        swarm.refresh();
      }),
    );

    // On click of the info button, show Dart info page in new window/tab.
    _infoButton.addOnClick((e) {
      // Bring up the config dialog.
      if (_infoDialog == null) {
        // TODO(terry): Cleanup, HeaderView shouldn't be tangled with main view.
        _infoDialog = HelpDialog(swarm.frontView, () {
          swarm.frontView.removeChild(_infoDialog!);
          _infoDialog = null;

          swarm.sections.refresh();
        });

        swarm.frontView.addChild(_infoDialog!);
      }
    });

    // On click of the new window button, show web article in new window/tab.
    _newWindowButton.addOnClick((e) {
      String currentArticleSrcUrl = swarm.state.currentArticle.value!.srcUrl;
      window.open(currentArticleSrcUrl, '_blank');
    });

    startTransitionToMainView();
  }

  /// Refreshes whether or not the buttons specific to the display of a story in
  /// the web perspective are visible.
  void refreshWebStoryButtons() {
    bool webButtonsHidden = true;

    if (swarm.state.currentArticle.value != null) {
      // Set if web buttons are hidden
      webButtonsHidden = swarm.state.storyTextMode.value;
    }

    _webBackButton.hidden = webButtonsHidden;
    _webForwardButton.hidden = webButtonsHidden;
    _newWindowButton.hidden = webButtonsHidden;
  }

  void startTransitionToMainView() {
    _title.removeClass('in-story');
    _backButton.removeClass('in-story');

    _configButton.removeClass('in-story');
    _refreshButton.removeClass('in-story');
    _infoButton.removeClass('in-story');

    refreshWebStoryButtons();
  }

  void endTransitionToStoryView() {
    _title.addClass('in-story');
    _backButton.addClass('in-story');

    _configButton.addClass('in-story');
    _refreshButton.addClass('in-story');
    _infoButton.addClass('in-story');
  }
}

/// A back button for the web view of a story that is equivalent to clicking
/// "back" in the browser. */
// TODO(rnystrom): We have nearly identical versions of this littered through
// the sample apps. Should consolidate into one.
class WebBackButton extends View {
  WebBackButton();

  @override
  Element render() {
    return Element.html('<div class="web-back-button button"></div>');
  }

  @override
  void afterRender(Element node) {
    addOnClick((e) {
      back();
    });
  }

  /// Equivalent to [window.history.back] */
  static void back() {
    window.history.back();
  }
}

/// A back button for the web view of a story that is equivalent to clicking
/// "forward" in the browser. */
// TODO(rnystrom): We have nearly identical versions of this littered through
// the sample apps. Should consolidate into one.
class WebForwardButton extends View {
  WebForwardButton();

  @override
  Element render() {
    return Element.html('<div class="web-forward-button button"></div>');
  }

  @override
  void afterRender(Element node) {
    addOnClick((e) {
      forward();
    });
  }

  /// Equivalent to [window.history.forward] */
  static void forward() {
    window.history.forward();
  }
}

/// A factory that creates a view for data sources.
class DataSourceViewFactory implements ViewFactory<Feed> {
  Swarm swarm;

  DataSourceViewFactory(this.swarm);

  @override
  View newView(Feed data) => DataSourceView(data, swarm);

  @override
  int get width => ArticleViewLayout.getSingleton().width;
  @override
  int? get height => null; // Width for this view isn't known.
}

/// A view for the items from a single data source.
/// Shows a title and a list of items.
class DataSourceView extends CompositeView {
  // TODO(jacobr): make this value be coupled with the CSS file.
  static const TAB_ONLY_HEIGHT = 34;

  final Feed source;
  late final VariableSizeListView<Article> itemsView;

  DataSourceView(this.source, Swarm swarm) : super('query') {
    // TODO(jacobr): make the title a view or decide it is sane for a subclass
    // of component view to manually add some DOM cruft.
    node.nodes.add(Element.html('<h2>${source.title}</h2>'));

    // TODO(jacobr): use named arguments when available.
    itemsView = addChild(
      VariableSizeListView<Article>(
        source.articles,
        ArticleViewFactory(swarm),
        true,
        /* scrollable */
        true,
        /* vertical */
        swarm.state.currentArticle,
        /* selectedItem */
        !Device.supportsTouch /* snapToArticles */,
        false /* paginate */,
        true /* removeClippedViews */,
        !Device.supportsTouch /* showScrollbar */,
      ),
    );
    itemsView.addClass('story-section');

    node.nodes.add(Element.html('<div class="query-name-shadow"></div>'));

    // Clicking the view (i.e. its title area) unmaximizes to show the entire
    // view.
    node.onMouseDown.listen((e) {
      swarm.state.storyMaximized.value = false;
    });
  }
}

/// A button that toggles between states. */
class ToggleButton extends View {
  EventListeners onChanged;
  List<String> states;

  ToggleButton(this.states) : onChanged = EventListeners();

  @override
  Element render() => Element.tag('button');

  @override
  void afterRender(Element node) {
    state = states[0];
    node.onClick.listen((event) {
      toggle();
    });
  }

  String get state {
    final currentState = node.innerHtml!;
    assert(states.contains(currentState));
    return currentState;
  }

  set state(String state) {
    assert(states.contains(state));
    node.innerHtml = state;
    onChanged.fire(null);
  }

  void toggle() {
    final oldState = state;
    int index = states.indexOf(oldState, 0);
    index = (index + 1) % states.length;
    state = states[index];
  }
}

/// A factory that creates a view for generic items.
class ArticleViewFactory implements VariableSizeViewFactory<Article> {
  Swarm swarm;

  ArticleViewLayout layout;
  ArticleViewFactory(this.swarm) : layout = ArticleViewLayout.getSingleton();

  @override
  View newView(Article item) => ArticleView(item, swarm, layout);

  @override
  int getWidth(Article? item) => layout.width;
  @override
  int getHeight(Article? item) => layout.computeHeight(item);
}

class ArticleViewMetrics {
  final int height;
  final int titleLines;
  final int bodyLines;

  const ArticleViewMetrics(this.height, this.titleLines, this.bodyLines);
}

class ArticleViewLayout {
  // TODO(terry): clean this up once we have a framework for sharing constants
  // between JS and CSS. See bug #5405307.
  static const IPAD_WIDTH = 257;
  static const DESKTOP_WIDTH = 297;
  static const CHROME_OS_WIDTH = 317;
  static const TITLE_MARGIN_LEFT = 257 - 150;
  static const BODY_MARGIN_LEFT = 257 - 221;
  static const LINE_HEIGHT = 18;
  static const TITLE_FONT = 'bold 13px arial,sans-serif';
  static const BODY_FONT = '13px arial,sans-serif';
  static const TOTAL_MARGIN = 16 * 2 + 70;
  static const MIN_TITLE_HEIGHT = 36;
  static const MAX_TITLE_LINES = 2;
  static const MAX_BODY_LINES = 4;

  MeasureText measureTitleText;
  MeasureText measureBodyText;

  int width;
  static ArticleViewLayout? _singleton;
  ArticleViewLayout()
    : measureBodyText = MeasureText(BODY_FONT),
      measureTitleText = MeasureText(TITLE_FONT),
      width = DESKTOP_WIDTH;

  static ArticleViewLayout getSingleton() {
    return _singleton ??= ArticleViewLayout();
  }

  int computeHeight(Article? item) {
    if (item == null) {
      // TODO(jacobr): find out why this is happening..
      print('Null item encountered.');
      return 0;
    }

    return computeLayout(item, null, null).height;
  }

  /// titleContainer and snippetContainer may be null in which case the size is
  /// computed but no actual layout is performed.
  ArticleViewMetrics computeLayout(
    Article item,
    StringBuffer? titleBuffer,
    StringBuffer? snippetBuffer,
  ) {
    int titleWidth = width - BODY_MARGIN_LEFT;

    if (item.hasThumbnail) {
      titleWidth = width - TITLE_MARGIN_LEFT;
    }

    final titleLines = measureTitleText.addLineBrokenText(
      titleBuffer,
      item.title,
      titleWidth,
      MAX_TITLE_LINES,
    );
    final bodyLines = measureBodyText.addLineBrokenText(
      snippetBuffer,
      item.textBody,
      width - BODY_MARGIN_LEFT,
      MAX_BODY_LINES,
    );

    int height = bodyLines * LINE_HEIGHT + TOTAL_MARGIN;

    if (bodyLines == 0) {
      height = 92;
    }

    return ArticleViewMetrics(height, titleLines, bodyLines);
  }
}

/// A view for a generic item.
class ArticleView extends View {
  // Set to false to make inspecting the HTML more pleasant...
  static const SAVE_IMAGES = false;

  final Article item;
  final Swarm swarm;
  final ArticleViewLayout articleLayout;

  ArticleView(this.item, this.swarm, this.articleLayout);

  @override
  Element render() {
    Element node;

    final byline = item.author.isNotEmpty ? item.author : item.dataSource.title;
    final date = DateUtils.toRecentTimeString(item.date);

    String storyClass = 'story no-thumb';
    String thumbnail = '';

    if (item.hasThumbnail) {
      storyClass = 'story';
      thumbnail = '<img src="${item.thumbUrl}"></img>';
    }

    final title = StringBuffer();
    final snippet = StringBuffer();

    // Note: also populates title and snippet elements.
    final metrics = articleLayout.computeLayout(item, title, snippet);

    node = Element.html('''
<div class="$storyClass">
  $thumbnail
  <div class="title">$title</div>
  <div class="byline">$byline</div>
  <div class="dateline">$date</div>
  <div class="snippet">$snippet</div>
</div>''');

    // Remove the snippet entirely if it's empty. This keeps it from taking up
    // space and pushing the padding down.
    if ((item.textBody == null) || (item.textBody.trim() == '')) {
      node.querySelector('.snippet')!.remove();
    }

    return node;
  }

  @override
  void afterRender(Element node) {
    // Select this view's item.
    addOnClick((e) {
      // Mark the item as read, so it shows as read in other views
      item.unread.value = false;

      final oldArticle = swarm.state.currentArticle.value;
      swarm.state.currentArticle.value = item;
      swarm.state.storyTextMode.value = true;
      if (oldArticle == null) {
        swarm.state.pushToHistory();
      }
    });

    watch(swarm.state.currentArticle, (e) {
      if (!swarm.state.inMainView) {
        swarm.state.markCurrentAsRead();
      }
      _refreshSelected(swarm.state.currentArticle);
      //TODO(efortuna): add in history stuff while reading articles?
    });

    watch(swarm.state.selectedArticle, (e) {
      _refreshSelected(swarm.state.selectedArticle);
      _updateViewForSelectedArticle();
    });

    watch(item.unread, (e) {
      // TODO(rnystrom): Would be nice to do:
      //     node.classes.set('story-unread', item.unread.value)
      if (item.unread.value) {
        node.classes.add('story-unread');
      } else {
        node.classes.remove('story-unread');
      }
    });
  }

  /// Notify the view to jump to a different area if we are selecting an
  /// article that is currently outside of the visible area.
  void _updateViewForSelectedArticle() {
    Article selArticle = swarm.state.selectedArticle.value!;
    if (swarm.state.hasArticleSelected) {
      // Ensure that the selected article is visible in the view.
      if (!swarm.state.inMainView) {
        // Story View.
        swarm.frontView.detachedView!.itemsView.showView(selArticle);
      } else {
        if (swarm.frontView.currentSection.inCurrentView(selArticle)) {
          // Scroll horizontally if needed.
          swarm.frontView.currentSection.dataSourceView!.showView(
            selArticle.dataSource,
          );
          DataSourceView dataView = swarm.frontView.currentSection.findView(
            selArticle.dataSource,
          );
          if (dataView != null) {
            dataView.itemsView.showView(selArticle);
          }
        }
      }
    }
  }

  String getDataUriForImage(final img) {
    // TODO(hiltonc,jimhug) eval perf of this vs. reusing one canvas element
    final CanvasElement canvas = CanvasElement(
      height: img.height,
      width: img.width,
    );

    final ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
    ctx.drawImageScaled(img, 0, 0, img.width, img.height);

    return canvas.toDataUrl("image/png");
  }

  /// Update this view's selected appearance based on the currently selected
  /// Article.
  void _refreshSelected(curItem) {
    if (curItem.value == item) {
      addClass('sel');
    } else {
      removeClass('sel');
    }
  }

  void _saveToStorage(String thumbUrl, ImageElement img) {
    // TODO(jimhug): Reimplement caching of images.
  }
}

/// An internal view of a story as text. In other words, the article is shown
/// in-place as opposed to as an embedded web-page.
class StoryContentView extends View {
  final Swarm swarm;
  final Article item;

  late View _pagedStory;

  StoryContentView(this.swarm, this.item);

  @override
  get childViews => [_pagedStory];

  @override
  Element render() {
    final storyContent = Element.html(
      '<div class="story-content">${item.htmlBody}</div>',
    );
    for (Element element in storyContent.querySelectorAll(
      "iframe, script, style, object, embed, frameset, frame",
    )) {
      element.remove();
    }
    _pagedStory = PagedContentView(View.fromNode(storyContent));

    // Modify all links to open in new windows....
    // TODO(jacobr): would it be better to add an event listener on click that
    // intercepts these instead?
    for (AnchorElement anchor in storyContent.querySelectorAll('a')) {
      anchor.target = '_blank';
    }

    final date = DateUtils.toRecentTimeString(item.date);
    final container = Element.html('''
      <div class="story-view">
        <div class="story-text-view">
          <div class="story-header">
            <a class="story-title" href="${item.srcUrl}" target="_blank">
              ${item.title}</a>
            <div class="story-byline">
              ${item.author} - ${item.dataSource.title}
            </div>
            <div class="story-dateline">$date</div>
          </div>
          <div class="paged-story"></div>
          <div class="spacer"></div>
        </div>
      </div>''');

    container.querySelector('.paged-story')!.replaceWith(_pagedStory.node);

    return container;
  }
}

class SectionView extends CompositeView {
  final Section section;
  final Swarm swarm;
  final DataSourceViewFactory _viewFactory;
  final View loadingText;
  ListView<Feed>? dataSourceView;
  late PageNumberView pageNumberView;
  final PageState pageState;

  SectionView(this.swarm, this.section, this._viewFactory)
    : loadingText = View.html('<div class="loading-section"></div>'),
      pageState = PageState(),
      super('section-view') {
    addChild(loadingText);
  }

  /// Hides the loading text, reloads the data sources, and shows them.
  void showSources() {
    loadingText.node.style.display = 'none';

    ListView<Feed>? dataView = dataSourceView;
    // Lazy initialize the data source view.
    if (dataView == null) {
      // TODO(jacobr): use named arguments when available.
      dataView = dataSourceView = ListView<Feed>(
        section.feeds,
        _viewFactory,
        true /* scrollable */,
        false /* vertical */,
        null /* selectedItem */,
        true /* snapToItems */,
        true /* paginate */,
        true /* removeClippedViews */,
        false,
        /* showScrollbar */
        pageState,
      );
      dataView.addClass("data-source-view");
      addChild(dataView);

      pageNumberView = addChild(PageNumberView(pageState));

      node.style.opacity = '1';
    } else {
      addChild(dataView);
      addChild(pageNumberView);
      node.style.opacity = '1';
    }

    // TODO(jacobr): get rid of this call to reconfigure when it is not needed.
    dataView.scroller!.reconfigure(() {});
  }

  /// Hides the data sources and shows the loading text.
  void hideSources() {
    if (dataSourceView != null) {
      node.style.opacity = '0.6';
      removeChild(dataSourceView!);
      removeChild(pageNumberView);
    }

    loadingText.node.style.display = 'block';
  }

  set storyMode(bool inStoryMode) {
    if (inStoryMode) {
      addClass('hide-all-queries');
    } else {
      removeClass('hide-all-queries');
    }
  }

  /// Find the [DataSourceView] in this SectionView that's displaying the given
  /// [Feed].
  DataSourceView findView(Feed dataSource) {
    return dataSourceView!.getSubview(dataSourceView!.findIndex(dataSource)!)
        as DataSourceView;
  }

  bool inCurrentView(Article article) {
    return dataSourceView!.findIndex(article.dataSource) != null;
  }
}
