"""
    Weighted Interval Scheduling - live coding
    1. N meeting requests, each with a start time and end time and a value
    2. Goal is to accept the subset of requests with largest total value
        but no conflicts
"""

from itertools import combinations
import random


class Meeting:
    def __init__(self, start, end, value):
        self.start = start
        self.end = end
        self.value = value

    def __repr__(self):
        return f"Meeting({self.start}, {self.end}, {self.value})"

    def __str__(self):
        return f"(({self.start}, {self.end}), {self.value})"  # ((3, 5), 2)

    def __eq__(self, other):
        return (
            self.start == other.start
            and self.end == other.end
            and self.value == other.value
        )

    def __hash__(self):
        return hash((self.start, self.end, self.value))

    def compatible(self, other):
        return self.end <= other.start or self.start >= other.end


class Solution:
    """
    A solution is a list or set (?) of meetings.
    It is not necessarily a VALID solution.
    """

    def __init__(self, meetings):
        self.meetings = set(meetings)

    def score(self):
        return sum(m.value for m in self.meetings)

    def is_valid(self):
        return all(m1.compatible(m2) for m1, m2 in combinations(self.meetings, 2))

    def tweak(self, all_meetings):
        assert isinstance(all_meetings, list)
        random_meeting = random.choice(all_meetings)

        # self.meetings = {Meeting(a,b,c), Meeting(d,e,f), Meeting(g,h,i)}

        new_solution = Solution(set(self.meetings))
        if random_meeting in self.meetings:
            new_solution.meetings.remove(random_meeting)
        else:
            new_solution.meetings.add(random_meeting)
        return new_solution
