aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/reading/models/Filter.scala
blob: 7ec6340a4ae0b14119667dd7377dca0daa37949c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package reading.models

trait Filter {
  def filter(book: Book): Boolean
  def kind: FilterKind
  def nonFormattedName: String
  def name: String

  override def equals(that: Any): Boolean =
    that match {
      case that: Filter =>
        this.kind == that.kind && this.name == that.name
      case _ =>
        false
    }

  override def hashCode: Int = this.kind.hashCode + this.nonFormattedName.hashCode
}

object Filter {
  def apply[T](in: T)(implicit filterFactory: FilterFactory[T]): Filter =
    filterFactory.create(in)

  def apply(kind: FilterKind, nonFormattedName: String): Option[Filter] =
    kind match {
      case FilterKind.Period => Period.withNameOption(nonFormattedName).map(apply[Period])
      case FilterKind.GroupedTheme => GroupedTheme.withNameOption(nonFormattedName).map(apply[GroupedTheme])
      case FilterKind.Theme => Theme.withNameOption(nonFormattedName).map(apply[Theme])
      case FilterKind.Genre => Genre.withNameOption(nonFormattedName).map(apply[Genre])
      case FilterKind.Level => Level.withNameOption(nonFormattedName).map(apply[Level])
      case FilterKind.Program => Program.withNameOption(nonFormattedName).map(apply[Program])
      case FilterKind.Grade => Grade.withNameOption(nonFormattedName).map(apply[Grade])
    }

  def contains(filters: Seq[Filter], filter: Filter): Boolean =
    filters.find(_ == filter).nonEmpty

  def remove(fs: Seq[Filter], rf: Filter): Seq[Filter] =
    fs.filterNot { f =>
      (f == rf
        || rf.kind == FilterKind.Grade && f.kind == FilterKind.Program
        || rf.kind == FilterKind.GroupedTheme && f.kind == FilterKind.Theme)
    }

  val onBooks: Map[Filter, Seq[Book]] =
    Seq(
      Grade.values.map(Filter.apply(_)),
      Program.values.map(Filter.apply(_)),
      Theme.values.map(Filter.apply(_)),
      GroupedTheme.values.map(Filter.apply(_)),
      Genre.values.map(Filter.apply(_)),
      Level.values.map(Filter.apply(_)),
      Period.values.map(Filter.apply(_))
    )
      .flatten
      .map(f => (f, Books().filter(f.filter)))
      .toMap

  def add(books: Seq[Book], filters: Seq[Filter]): Seq[Book] =
    filters.foldLeft(books)(add)

  def add(books: Seq[Book], filter: Filter): Seq[Book] =
    books.intersect(onBooks.getOrElse(filter, Nil))

}