import abc
from datetime import datetime

from Matching.GroupingAlgo import group
from Models import ProjectModel, ChannelModel, PostModel, UserModel
from Notify.Firebase import notify_study_group
from app import db


def make_learn_group(users, group_name):
    channel = ChannelModel()
    db.session.add(channel)
    post = PostModel(channel=channel,
                     content="Willkommen in eurem Lerngruppen chat :), Welcome to your Study group chat :)",
                     date_created=datetime.utcnow(),
                     author=UserModel.matchinit_user())
    db.session.add(post)
    db.session.add(channel)

    project = ProjectModel(name=group_name, channel=channel, is_visible=False)
    project.attendees.extend(users)
    db.session.add(project)
    db.session.commit()
    notify_study_group(project)
    return project


class AbstractGroupMatcher(metaclass=abc.ABCMeta):
    """
    override get_metric and query_users to become concrete
    """

    def __init__(self, group_name):
        self.metric = self.get_metric()
        self.group_name = group_name

    def trigger_matching(self, group_size: int):
        def distance(user_one, user_two):
            self.metric.reset_user(user_one)
            score = self.metric.get_score(user_two)
            if score <= 0.1:
                score = 0.1
            return 10 / score
        grouping_result = group(self.query_users(), distance, group_size)

        self.after_successful_matching()
        return [make_learn_group(grouping, self.group_name) for grouping in grouping_result]

    @abc.abstractmethod
    def get_metric(self):
        """
        returns a metric factory
        """

    @abc.abstractmethod
    def query_users(self):
        """
        returns list of users that could be matched
        """

    @abc.abstractmethod
    def after_successful_matching(self):
        """
        returns list of users that could be matched
        """
