summaryrefslogtreecommitdiff
path: root/fake-service/lib/pixelated_service/mail_service.rb
blob: 02e36835644bc8fcd782305820c71feeff3a69ff (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
require 'set'

module PixelatedService
  class MailService
    include Enumerable
    include PixelatedService::Stats

    def each
      @mails.each do |mo|
        yield mo
      end
    end

    def initialize
      self.clean
    end

    def contact(ix)
      @contacts.contact(ix)
    end

    def contacts
      @contacts.to_a
    end

    def clean
      PixelatedService::Tags.clean
      @next_ident = 0
      @reply_drafts = {}
      @mails = SortedMail.new
      @contacts = Contacts.new(Fake::PERSONAS[0])
      @observers = CombinedObserver.new(StatsObserver.new(self),
                                        ContactsObserver.new(@contacts))
    end

    def create(mail=Generator.random_mail)
      unless mail.ident
        mail.ident = @next_ident
        @next_ident += 1
      end
      @mails[mail.ident] = mail
      @observers.mail_added(mail)
    end

    def create_tag(tag_json)
      PixelatedService::Tags.create_tag tag_json['tag']
    end

    def mail(ix)
      @mails[ix.to_i]
    end

    def send_mail(data)
      ms = Mail.from_json(data, @next_ident)
      if ms.tag_names.include?("sent")
        ms.remove_tag "drafts"
        @reply_drafts.delete ms.draft_reply_for
      elsif ms.tag_names.include?("drafts") and ms.draft_reply_for
        @reply_drafts[ms.draft_reply_for] = ms.ident
      end
      @next_ident += 1
      @mails[ms.ident] = ms
      update_status ms
      @observers.mail_added(ms)
      ms.ident
    end

    def draft_reply_for(ident)
      @mails[@reply_drafts[ident.to_i]]
    end

    def update_mail(data)
      mail = Mail.from_json(data)
      before = @mails[mail.ident]
      @mails[mail.ident] = mail
      update_status mail
      @observers.mail_updated(before, mail)
      before.tags = nil
      mail.ident
    end

    def update_status(mail)
      mail.read = true
      mail.headers[:date] = Time.now
    end

    def tags(q)
      if q && !q.strip.empty?
        query = /\b#{Regexp.new(Regexp.quote(q), Regexp::IGNORECASE)}/
        PixelatedService::Tags.all_tags.select do |tt|
          query =~ tt.name
        end
      else
        PixelatedService::Tags.all_tags
      end
    end

    def stats_report
      { stats: self.stats }
    end

    def delete_mail(ix)
      ms = @mails[ix.to_i]
      @reply_drafts.delete ms.draft_reply_for

      if ms.has_trash_tag?
        m = @mails.delete ix.to_i
        @observers.mail_removed(m)
        m.tags = nil
      else
        ms.add_tag 'trash'
      end
    end

    def load_mailset(name)
      self.clean
      ms = PixelatedService::Mailset.load(name, @observers)
      raise "couldn't find mailset #{name}" unless ms
      @mails.add_all ms.mails
      self.stats
    end

    def mails(q, page, window_size)
      restrictors = [All.new]
      restrictors << Paginate.new(page, window_size) if window_size > 0
      restrictors << Search.new(q)
      with_stats(restrictors.reverse.inject(self) do |ms, restr|
        restr.restrict(ms)
      end)
    end

    def contacts(q, page, window_size)
      restrictors = [All.new]
      restrictors << ContactsSorter.new
      restrictors << Paginate.new(page, window_size) if window_size > 0
      restrictors << ContactsSearch.new(q) if q
      restrictors.reverse.inject(@contacts) do |c, restr|
        restr.restrict(c)
      end
    end

    def delete_mails(q, page, window_size, idents=nil)
      unless idents.nil?
        @mails.each { |k,v| delete_mail(k.ident) if idents.include?(k.ident) }
      else
        mails(q, page, window_size).each do |m|
          delete_mail m.ident
        end
      end
    end
  end
end