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

  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!
  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 callback(Sections sects)) {
    final decoder = new Decoder(data);
    int nSections = decoder.readInt();
    final sections = new List<Section>();

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

  static void initializeFromUrl(
      bool useCannedData, void callback(Sections sections)) {
    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
  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 = new ObservableList<Feed>();
    for (int j = 0; j < nSources; j++) {
      feeds.add(Feed.decode(decoder));
    }
    return new 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 = new ObservableList<Article>(),
        error = new ObservableValue<bool>(false);

  static Feed decode(Decoder decoder) {
    final sourceId = decoder.readString();
    final sourceTitle = decoder.readString();
    final sourceIcon = decoder.readString();
    final feed = new 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: null, bool unread: true, this.error: false})
      : unread = new ObservableValue<bool>(unread),
        this._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;

    var 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 = new 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 = new DateTime.fromMillisecondsSinceEpoch(dateInSeconds * 1000,
        isUtc: true);
    return new Article(
        source, id, date, title, author, srcUrl, hasThumbnail, snippet);
  }
}
