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

/// The top-level collection of all sections for a user. */
// TODO(jimhug): This is known as UserData in the server model.
class Sections extends IterableBase<Section> {
  final List<Section> _sections;

  Sections(this._sections);

  operator [](int i) => _sections[i];

  @override
  int get length => _sections.length;

  List<String> get sectionTitles => _sections.map((s) => s.title).toList();

  void refresh() {
    // TODO(jimhug): http://b/issue?id=5351067
  }

  /// Find the Section object that has a given title.
  /// This is used to integrate well with [ConveyorView].
  Section findSection(String name) {
    return CollectionUtils.find(_sections, (sect) => sect.title == name);
  }

  // TODO(jimhug): Track down callers!
  @override
  Iterator<Section> get iterator => _sections.iterator;

  // TODO(jimhug): Better support for switching between local dev and server.
  static bool get runningFromFile {
    return window.location.protocol.startsWith('file:');
  }

  static String get home {
    // TODO(jmesserly): window.location.origin not available on Safari 4.
    // Move this workaround to the DOM code. See bug 5389503.
    return '${window.location.protocol}//${window.location.host}';
  }

  // This method is exposed for tests.
  static void initializeFromData(
    String data,
    void Function(Sections sects) callback,
  ) {
    final decoder = Decoder(data);
    int nSections = decoder.readInt();
    final sections = <Section>[];

    for (int i = 0; i < nSections; i++) {
      sections.add(Section.decode(decoder));
    }
    callback(Sections(sections));
  }

  static void initializeFromUrl(
    bool useCannedData,
    void Function(Sections sections) callback,
  ) {
    if (Sections.runningFromFile || useCannedData) {
      initializeFromData(CannedData.data['user.data']!, callback);
    } else {
      // TODO(jmesserly): display an error if we fail here! Silent failure bad.
      HttpRequest.getString('data/user.data').then(
        EventBatch.wrap((responseText) {
          // TODO(jimhug): Nice response if get error back from server.
          // TODO(jimhug): Might be more efficient to parse request
          // in sections.
          initializeFromData(responseText, callback);
        }),
      );
    }
  }

  Section findSectionById(String id) {
    return CollectionUtils.find(_sections, (section) => section.id == id);
  }

  /// Given the name of a section, find its index in the set.
  int findSectionIndex(String name) {
    for (int i = 0; i < _sections.length; i++) {
      if (name == _sections[i].title) {
        return i;
      }
    }
    return -1;
  }

  List<Section> get sections => _sections;

  // TODO(jmesserly): this should be a property
  @override
  bool get isEmpty => length == 0;
}

/// A collection of data sources representing a page in the UI. */
class Section {
  final String id;
  final String title;
  ObservableList<Feed> feeds;

  // Public for testing. TODO(jacobr): find a cleaner solution.
  Section(this.id, this.title, this.feeds);

  void refresh() {
    for (final feed in feeds) {
      // TODO(jimhug): http://b/issue?id=5351067
    }
  }

  static Section decode(Decoder decoder) {
    final sectionId = decoder.readString();
    final sectionTitle = decoder.readString();

    final nSources = decoder.readInt();
    final feeds = ObservableList<Feed>();
    for (int j = 0; j < nSources; j++) {
      feeds.add(Feed.decode(decoder));
    }
    return Section(sectionId, sectionTitle, feeds);
  }

  Feed findFeed(String id_) {
    return CollectionUtils.find(feeds, (feed) => feed.id == id_);
  }
}

/// Provider of a news feed. */
class Feed {
  String id;
  final String title;
  final String iconUrl;
  final String description;
  ObservableList<Article> articles;
  ObservableValue<bool> error; // TODO(jimhug): Check if dead code.

  Feed(this.id, this.title, this.iconUrl, {this.description = ''})
    : articles = ObservableList<Article>(),
      error = ObservableValue<bool>(false);

  static Feed decode(Decoder decoder) {
    final sourceId = decoder.readString();
    final sourceTitle = decoder.readString();
    final sourceIcon = decoder.readString();
    final feed = Feed(sourceId, sourceTitle, sourceIcon);
    final nItems = decoder.readInt();

    for (int i = 0; i < nItems; i++) {
      feed.articles.add(Article.decodeHeader(feed, decoder));
    }
    return feed;
  }

  Article findArticle(String id_) {
    return CollectionUtils.find(articles, (article) => article.id == id_);
  }

  void refresh() {}
}

/// A single article or posting to display. */
class Article {
  final String id;
  DateTime date;
  final String title;
  final String author;
  final bool hasThumbnail;
  String textBody; // TODO(jimhug): rename to snippet.
  final Feed dataSource; // TODO(jimhug): rename to feed.
  String _htmlBody;
  String srcUrl;
  final ObservableValue<bool> unread; // TODO(jimhug): persist to server.

  bool error; // TODO(jimhug): Check if this is dead and remove.

  Article(
    this.dataSource,
    this.id,
    this.date,
    this.title,
    this.author,
    this.srcUrl,
    this.hasThumbnail,
    this.textBody, {
    htmlBody,
    bool unread = true,
    this.error = false,
  }) : unread = ObservableValue<bool>(unread),
       _htmlBody = htmlBody;

  String get htmlBody {
    _ensureLoaded();
    return _htmlBody;
  }

  String get dataUri {
    return SwarmUri.encodeComponent(
      id,
    )!.replaceAll('%2F', '/').replaceAll('%253A', '%3A');
  }

  String? get thumbUrl {
    if (!hasThumbnail) return null;

    String home;
    if (Sections.runningFromFile) {
      home = 'http://dart.googleplex.com';
    } else {
      home = Sections.home;
    }
    // By default images from the real server are cached.
    // Bump the version flag if you change the thumbnail size, and you want to
    // get the new images. Our server ignores the query params but it gets
    // around appengine server side caching and the client side cache.
    return 'data/$dataUri.jpg';
  }

  // TODO(jimhug): need to return a lazy Observable<String> and also
  //   add support for preloading.
  void _ensureLoaded() {
    if (_htmlBody != null) return;

    var name = '$dataUri.html';
    if (Sections.runningFromFile) {
      _htmlBody = CannedData.data[name]!;
    } else {
      // TODO(jimhug): Remove this truly evil synchronous xhr.
      final req = HttpRequest();
      req.open('GET', 'data/$name', async: false);
      req.send();
      _htmlBody = req.responseText!;
    }
  }

  static Article decodeHeader(Feed source, Decoder decoder) {
    final id = decoder.readString();
    final title = decoder.readString();
    final srcUrl = decoder.readString();
    final hasThumbnail = decoder.readBool();
    final author = decoder.readString();
    final dateInSeconds = decoder.readInt();
    final snippet = decoder.readString();
    final date = DateTime.fromMillisecondsSinceEpoch(
      dateInSeconds * 1000,
      isUtc: true,
    );
    return Article(
      source,
      id,
      date,
      title,
      author,
      srcUrl,
      hasThumbnail,
      snippet,
    );
  }
}
