<commit_before>//
//  MangasViewModel.swift
//  Yomu
//
//  Created by <NAME> on 7/3/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import class RealmSwift.Realm
import RxCocoa
import RxMoya
import RxSwift
import RxRealm
import Swiftz

struct SelectedIndex {
  let previousIndex: Int
  let index: Int
}


struct MangaCollectionViewModel {
  private let _selectedIndex = Variable(SelectedIndex(previousIndex: -1, index: -1))
  private var _fetching = Variable(false)
  private var _mangas: Variable<OrderedSet<Manga>> = {
    let mangas = Database.queryMangas().sorted {
      $0.position < $1.position
    }

    return Variable(OrderedSet(elements: mangas))
  }()
  private let recentlyDeletedManga: Variable<Manga?> = Variable(.none)
  private var mangaViewModels = Variable(List<MangaViewModel>())

  var mangas: Driver<List<MangaViewModel>> {
    return mangaViewModels.asDriver()
  }

  var count: Int {
    return mangaViewModels.value.count
  }

  var fetching: Driver<Bool> {
    return _fetching.asDriver()
  }

  var disposeBag = DisposeBag()

  init() {
    recentlyDeletedManga
      .asObservable()
      .filter { $0 != nil }
      .map { manga in
        let id = manga?.id

        return Database.queryMangaRealm(id: id!)
      }
      .subscribe(Realm.rx.delete()) ==> disposeBag

    let this = self

    _mangas.asObservable() ~~> {
      let viewModels = $0.flatMap(MangaViewModel.init)
      this.mangaViewModels.value = List(fromArray: viewModels)
    } ==> disposeBag

    _mangas
      .asObservable()
      .filter { $0.count != 0 }
      .flatMap { Observable.from($0) }
      .map(MangaRealm.from(manga:))
      .subscribe(Realm.rx.add(update: true)) ==> disposeBag
  }

  subscript(index: Int) -> MangaViewModel {
    return mangaViewModels.value[UInt(index)]
  }

  func fetch(id: String) -> Disposable {
    let api = MangaEdenAPI.mangaDetail(id)

    _fetching.value = true

    return MangaEden
      .request(api)
      .do(onCompleted: { self._fetching.value = false })
      .filterSuccessfulStatusCodes()
      .map(Manga.self)
      .subscribe(onNext: {
        var manga = $0
        manga.id = id
        manga.position = self.count

        // Manga already in collection
        if self._mangas.value.contains(manga) {
          return
        }

        self._mangas.value.append(element: manga)

        for (index, var manga) in self._mangas.value.enumerated() {
          if manga.position == MangaPosition.undefined.rawValue {
            manga.position = index
          }
        }
      })
  }

  func setSelectedIndex(_ index: Int) {
    let previous = _selectedIndex.value
    let selectedIndex = SelectedIndex(previousIndex: previous.index, index: index)
    _selectedIndex.value = selectedIndex

    if selectedIndex.previousIndex != -1 {
      self[selectedIndex.previousIndex].setSelected(false)
    }

    self[selectedIndex.index].setSelected(true)
  }

  func move(fromIndex: Int, toIndex: Int) {
    let manga = self[fromIndex].manga
    _mangas.value.remove(index: fromIndex)
    _mangas.value.insert(element: manga, atIndex: toIndex)

    let indexes: [Int] = [Int](0..<self.count)
    let mangas: [Manga] = indexes.map {
      var manga = self._mangas.value[$0]
      manga.position = $0

      return manga
    }

    _mangas.value = OrderedSet(elements: mangas)
  }

  func remove(mangaIndex: Int) {
    recentlyDeletedManga.value = _mangas.value.remove(index: mangaIndex)
  }
}<commit_msg>Update all manga positions on removed<commit_after>//
//  MangasViewModel.swift
//  Yomu
//
//  Created by <NAME> on 7/3/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import class RealmSwift.Realm
import RxCocoa
import RxMoya
import RxSwift
import RxRealm
import Swiftz

struct SelectedIndex {
  let previousIndex: Int
  let index: Int
}


struct MangaCollectionViewModel {
  private let _selectedIndex = Variable(SelectedIndex(previousIndex: -1, index: -1))
  private var _fetching = Variable(false)
  private var _mangas: Variable<OrderedSet<Manga>> = {
    let mangas = Database.queryMangas().sorted {
      $0.position < $1.position
    }

    return Variable(OrderedSet(elements: mangas))
  }()
  private let recentlyDeletedManga: Variable<Manga?> = Variable(.none)
  private var mangaViewModels = Variable(List<MangaViewModel>())

  var mangas: Driver<List<MangaViewModel>> {
    return mangaViewModels.asDriver()
  }

  var count: Int {
    return mangaViewModels.value.count
  }

  var fetching: Driver<Bool> {
    return _fetching.asDriver()
  }

  var disposeBag = DisposeBag()

  init() {
    recentlyDeletedManga
      .asObservable()
      .filter { $0 != nil }
      .map { manga in
        let id = manga?.id

        return Database.queryMangaRealm(id: id!)
      }
      .subscribe(Realm.rx.delete()) ==> disposeBag

    let this = self

    _mangas.asObservable() ~~> {
      let viewModels = $0.flatMap(MangaViewModel.init)
      this.mangaViewModels.value = List(fromArray: viewModels)
    } ==> disposeBag

    _mangas
      .asObservable()
      .filter { $0.count != 0 }
      .flatMap { Observable.from($0) }
      .map(MangaRealm.from(manga:))
      .subscribe(Realm.rx.add(update: true)) ==> disposeBag
  }

  subscript(index: Int) -> MangaViewModel {
    return mangaViewModels.value[UInt(index)]
  }

  func fetch(id: String) -> Disposable {
    let api = MangaEdenAPI.mangaDetail(id)

    _fetching.value = true

    return MangaEden
      .request(api)
      .do(onCompleted: { self._fetching.value = false })
      .filterSuccessfulStatusCodes()
      .map(Manga.self)
      .subscribe(onNext: {
        var manga = $0
        manga.id = id
        manga.position = self.count

        // Manga already in collection
        if self._mangas.value.contains(manga) {
          return
        }

        self._mangas.value.append(element: manga)

        for (index, var manga) in self._mangas.value.enumerated() {
          if manga.position == MangaPosition.undefined.rawValue {
            manga.position = index
          }
        }
      })
  }

  func setSelectedIndex(_ index: Int) {
    let previous = _selectedIndex.value
    let selectedIndex = SelectedIndex(previousIndex: previous.index, index: index)
    _selectedIndex.value = selectedIndex

    if selectedIndex.previousIndex != -1 {
      self[selectedIndex.previousIndex].setSelected(false)
    }

    self[selectedIndex.index].setSelected(true)
  }

  func move(fromIndex: Int, toIndex: Int) {
    let manga = self[fromIndex].manga
    _mangas.value.remove(index: fromIndex)
    _mangas.value.insert(element: manga, atIndex: toIndex)
    updateMangaPositions()
  }

  func remove(mangaIndex: Int) {
    recentlyDeletedManga.value = _mangas.value.remove(index: mangaIndex)
    updateMangaPositions()
  }

  private func updateMangaPositions() {
    let indexes: [Int] = [Int](0..<self.count)
    let mangas: [Manga] = indexes.map {
      var manga = self._mangas.value[$0]
      manga.position = $0

      return manga
    }

    _mangas.value = OrderedSet(elements: mangas)
  }
}
{'fraction_non_alphanumeric': 0.11511199319535016, 'fraction_numerical': 0.0062375956903884325, 'mean_word_length': 2.815575987020011, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7240698', 'n_tokens_mistral': 2415, 'n_tokens_neox': 2266, 'n_words': 480}