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

// @dart = 2.9


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