import sys
import os
modules_path = '../../../modules/'
if os.path.exists(modules_path):
    sys.path.insert(1, modules_path)

from db.entities import Location, PopularLocation, LocationCluster, TimeCluster
from typing import List, Dict, Tuple
from db.repository import Repository
from processing.clusterer import Clusterer


DEBUG = False

repo = Repository()

def run_location_clustering():
    user_clusterer = Clusterer()

    all_location_traces = repo.get_locations()

    cluster_result = user_clusterer.cluster_locations(
        [l.to_serializable_dict() for l in all_location_traces])

    clusters = [LocationCluster(key, value)
                for key, value in cluster_result.items()]

    store_clusters('locations', clusters)


def run_time_clustering():
    clusters: List[TimeCluster] = []
    user_clusterer = Clusterer(epsilon=600)  # clustered within 10 minutes

    all_location_traces = repo.get_locations()

    # for each date in timestamp list
    dates = {trace.timestamp.date() for trace in all_location_traces}
    for cur_date in dates:
        traces_for_cur_date = [
            trace for trace in all_location_traces if trace.timestamp.date() == cur_date]

        # for each hour of that day
        for cur_hour in list(range(24)):
            traces_for_time_slice = [
                trace for trace in traces_for_cur_date if trace.timestamp.hour == cur_hour]

            if len(traces_for_time_slice) == 0:
                continue

            # clustering per hour
            cluster_result = user_clusterer.cluster_times(
                [t.to_serializable_dict() for t in traces_for_time_slice])
            cur_clusters = [TimeCluster(cur_date, cur_hour, key, value)
                            for key, value in cluster_result.items()]

            clusters.extend(cur_clusters)

    store_clusters('times', clusters)


def store_clusters(type: str, clusters: List):
    if DEBUG:
        print(clusters)
        return

    if type == 'locations':
        for c in clusters:
            repo.add_location_cluster(c)

    if type == 'times':
        for c in clusters:
            repo.add_time_cluster(c)


if __name__ == "__main__":
    run_location_clustering()
    run_time_clustering()
