aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/reading/models/Filter.scala
blob: b8adcc16f855aef8f6f17ad0b5a5f6bd1424e1db (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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package reading.models

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

sealed trait FilterKind
case object PeriodKind extends FilterKind
case object ThemeKind extends FilterKind
case object GenreKind extends FilterKind
case object DifficultyKind extends FilterKind
case object ProgramKind extends FilterKind
case object LevelKind extends FilterKind

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

  def contains(filters: Seq[Filter], filter: Filter): Boolean =
    filters.find(f => f.kind == filter.kind && f.name == filter.name).nonEmpty

  def equals(f1: Filter, f2: Filter): Boolean =
    f1.kind == f2.kind && f1.name == f2.name

  def remove(fs: Seq[Filter], rf: Filter): Seq[Filter] =
    fs.filterNot { f =>
      equals(f, rf) || rf.kind == LevelKind && f.kind == ProgramKind
    }
}

trait FilterFactory[T] {
  def create(in: T): Filter
}

object FilterFactory {
  implicit object PeriodFilter extends FilterFactory[Period] {
    def create(period: Period): Filter =
      new Filter {
        def filter(book: Book): Boolean = book.period == period
        val kind: FilterKind = PeriodKind
        val name: String = period.toString()
      }
  }

  implicit object ThemeFilter extends FilterFactory[Theme] {
    def create(theme: Theme): Filter =
      new Filter {
        def filter(book: Book): Boolean = book.themes.contains(theme)
        val kind: FilterKind = ThemeKind
        val name: String = theme.toString()
      }
  }

  implicit object GenreFilter extends FilterFactory[Genre] {
    def create(genre: Genre): Filter =
      new Filter {
        def filter(book: Book): Boolean = book.genres.contains(genre)
        val kind: FilterKind = GenreKind
        val name: String = genre.toString()
      }
  }

  implicit object ProgramFilter extends FilterFactory[Program] {
    def create(program: Program): Filter =
      new Filter {
        def filter(book: Book): Boolean = book.programs.contains(program)
        val kind: FilterKind = ProgramKind
        val name: String = program.toString()
      }
  }

  implicit object LevelFilter extends FilterFactory[Level] {
    def create(level: Level): Filter =
      new Filter {
        def filter(book: Book): Boolean = book.programs.map(Program.level).contains(level)
        val kind: FilterKind = LevelKind
        val name: String = level.toString()
      }
  }
}