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