# Path: kittystore/events.py
# def subscribe(target, eventclass):
# def notify(event):
# def subscribe_to(eventclass):
#     def wrapper(f):
# def reset():
# 
# Path: kittystore/utils.py
# def get_message_id_hash(msg_id):
#     """
#     Returns the X-Message-ID-Hash header for the provided Message-ID header.
# 
#     See <http://wiki.list.org/display/DEV/Stable+URLs#StableURLs-Headers> for
#     details. Example:
# 
#     >>> get_message_id_hash('<87myycy5eh.fsf@uwakimon.sk.tsukuba.ac.jp>')
#     'JJIGKPKB6CVDX6B2CUG4IHAJRIQIOUTP'
# 
#     """
#     msg_id = email.utils.unquote(msg_id)
#     return unicode(b32encode(sha1(msg_id).digest()))
# 
# Path: kittystore/sa/utils.py
# def get_participants_count_between(session, list_name, begin_date, end_date):
#         from .model import Email
#         # We filter on emails dates instead of threads dates because that would
#         # also include last month's participants when threads carry from one
#         # month to the next
#         result = session.query(Email.sender_email).filter(and_(
#                         Email.list_name == list_name,
#                         Email.date >= begin_date,
#                         Email.date < end_date,
#                         )).distinct()
#         return result.count()
#         # TODO: check that ------v
#         #return result.count() # generates a sub-query
#         return len(list(result))
# 
# def get_threads_between(session, list_name, begin_date, end_date):
#         from .model import Thread
#         return session.query(Thread).filter(and_(
#                     Thread.list_name == list_name,
#                     Thread.date_active >= begin_date,
#                     Thread.date_active < end_date,
#                 ))


import datetime
from collections import namedtuple
from zope.interface import implements
from mailman.interfaces.archiver import ArchivePolicy
from mailman.interfaces.messages import IMessage
from mailman.database.types import Enum, UUID
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy import and_, desc
from sqlalchemy import Column, ForeignKey, Integer, Unicode, UnicodeText
from sqlalchemy import DateTime, LargeBinary
from sqlalchemy.types import TypeDecorator
from sqlalchemy.orm import relationship, backref, object_session
from sqlalchemy.sql import expression
from sqlalchemy.schema import ForeignKeyConstraint, Index
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy import event as sa_event
from kittystore import events
from kittystore.utils import get_message_id_hash
from .utils import get_participants_count_between, get_threads_between

    @property
    def recent_threads_count(self):
        begin_date, end_date = self.get_recent_dates()
        session = object_session(self)
        return session.cache.get_or_create(
            str("list:%s:recent_threads_count" % self.name),
            lambda: get_threads_between(session, self.name,
                                        begin_date, end_date).count(),
            86400)

    def get_month_activity(self, year, month):
        session = object_session(self)
        begin_date = datetime.datetime(year, month, 1)
        end_date = begin_date + datetime.timedelta(days=32)
        end_date = end_date.replace(day=1)
        participants_count = session.cache.get_or_create(
            str("list:%s:participants_count:%s:%s" % (self.name, year, month)),
            lambda: get_participants_count_between(session, self.name,
                                                   begin_date, end_date),
            )
        threads_count = session.cache.get_or_create(
            str("list:%s:threads_count:%s:%s" % (self.name, year, month)),
            lambda: get_threads_between(session, self.name,
                                        begin_date, end_date).count(),
            )
        Activity = namedtuple('Activity',
                ['year', 'month', 'participants_count', 'threads_count'])
        return Activity(year, month, participants_count, threads_count)


# Path: kittystore/events.py
# def subscribe(target, eventclass):
# def notify(event):
# def subscribe_to(eventclass):
#     def wrapper(f):
# def reset():
# 
# Path: kittystore/utils.py
# def get_message_id_hash(msg_id):
#     """
#     Returns the X-Message-ID-Hash header for the provided Message-ID header.
# 
#     See <http://wiki.list.org/display/DEV/Stable+URLs#StableURLs-Headers> for
#     details. Example:
# 
#     >>> get_message_id_hash('<87myycy5eh.fsf@uwakimon.sk.tsukuba.ac.jp>')
#     'JJIGKPKB6CVDX6B2CUG4IHAJRIQIOUTP'
# 
#     """
#     msg_id = email.utils.unquote(msg_id)
#     return unicode(b32encode(sha1(msg_id).digest()))
# 
# Path: kittystore/sa/utils.py
# def get_participants_count_between(session, list_name, begin_date, end_date):
#         from .model import Email
#         # We filter on emails dates instead of threads dates because that would
#         # also include last month's participants when threads carry from one
#         # month to the next
#         result = session.query(Email.sender_email).filter(and_(
#                         Email.list_name == list_name,
#                         Email.date >= begin_date,
#                         Email.date < end_date,
#                         )).distinct()
#         return result.count()
#         # TODO: check that ------v
#         #return result.count() # generates a sub-query
#         return len(list(result))
# 
# def get_threads_between(session, list_name, begin_date, end_date):
#         from .model import Thread
#         return session.query(Thread).filter(and_(
#                     Thread.list_name == list_name,
#                     Thread.date_active >= begin_date,
#                     Thread.date_active < end_date,
#                 ))


# Path: kittystore/sa/model.py
import datetime
from collections import namedtuple
from zope.interface import implements
from mailman.interfaces.archiver import ArchivePolicy
from mailman.interfaces.messages import IMessage
from mailman.database.types import Enum, UUID
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy import and_, desc
from sqlalchemy import Column, ForeignKey, Integer, Unicode, UnicodeText
from sqlalchemy import DateTime, LargeBinary
from sqlalchemy.types import TypeDecorator
from sqlalchemy.orm import relationship, backref, object_session
from sqlalchemy.sql import expression
from sqlalchemy.schema import ForeignKeyConstraint, Index
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy import event as sa_event
from kittystore import events
from kittystore.utils import get_message_id_hash
from .utils import get_participants_count_between, get_threads_between


    @property
    def recent_threads_count(self):
        begin_date, end_date = self.get_recent_dates()
        session = object_session(self)
        return session.cache.get_or_create(
            str("list:%s:recent_threads_count" % self.name),
            lambda: get_threads_between(session, self.name,
                                        begin_date, end_date).count(),
            86400)

    def get_month_activity(self, year, month):
        session = object_session(self)
        begin_date = datetime.datetime(year, month, 1)
        end_date = begin_date + datetime.timedelta(days=32)
        end_date = end_date.replace(day=1)
        participants_count = session.cache.get_or_create(
            str("list:%s:participants_count:%s:%s" % (self.name, year, month)),
            lambda: get_participants_count_between(session, self.name,
                                                   begin_date, end_date),
            )
        threads_count = session.cache.get_or_create(
            str("list:%s:threads_count:%s:%s" % (self.name, year, month)),
            lambda: get_threads_between(session, self.name,
                                        begin_date, end_date).count(),
            )
        Activity = namedtuple('Activity',
                ['year', 'month', 'participants_count', 'threads_count'])
        return Activity(year, month, participants_count, threads_count)


    @events.subscribe_to(events.NewMessage)