from datetime import datetime, timedelta

from robit.core.cron import Cron

CREATED_DATE_FORMAT = '%b %d, %Y %I:%M%p'


class Clock:
    def __init__(
            self,
            cron: str = '* * * * *',
            utc_offset: int = 0,
            timer_duration_list_max: int = 10
    ):
        self.cron = Cron(value=cron, utc_offset=utc_offset)

        self.utc_offset = utc_offset

        self.created_utc = datetime.utcnow()
        self.created_tz = datetime.utcnow() + timedelta(hours=utc_offset)

        self.timer_duration_list_max = timer_duration_list_max
        self.timer_duration_list = []
        self.timer_average_duration = 0.0
        self.timer_last_duration = 0.0
        self.timer_shortest_duration = 0.0
        self.timer_longest_duration = 0.0
        self.timer = None

    def as_dict(self):
        return {
            'created': self.created_tz_verbose,
            'now': self.now_tz_verbose,
            'next_run_datetime': self.next_run_datetime_verbose,
            'timer_last_duration': f'{self.timer_last_duration:.2f}',
            'timer_average_duration': f'{self.timer_average_duration:.2f}',
            'timer_shortest_duration': f'{self.timer_shortest_duration:.2f}',
            'timer_longest_duration': f'{self.timer_longest_duration:.2f}',
        }

    def calculate_timer_average_duration(self):
        timer_total_duration = 0.0
        if len(self.timer_duration_list) > 0:
            for timer_duration in self.timer_duration_list:
                timer_total_duration += timer_duration
            self.timer_average_duration = timer_total_duration / len(self.timer_duration_list)

    @property
    def created_utc_verbose(self):
        return self.created_utc.strftime(CREATED_DATE_FORMAT)

    @property
    def created_tz_verbose(self):
        return self.created_tz.strftime(CREATED_DATE_FORMAT)

    @property
    def now_tz_verbose(self):
        return (datetime.utcnow() + timedelta(hours=self.utc_offset)).strftime(CREATED_DATE_FORMAT)

    def is_past_next_run_datetime(self):
        if self.cron.is_past_next_datetime():
            return True
        else:
            return False

    @property
    def next_run_datetime_verbose(self):
        return self.cron.next_datetime.strftime(CREATED_DATE_FORMAT)

    def start_timer(self):
        self.timer = datetime.utcnow()

    def stop_timer(self):
        duration = (datetime.utcnow() - self.timer).total_seconds()

        self.timer_last_duration = duration
        self.timer_duration_list.insert(0, duration)

        if self.timer_shortest_duration == 0 or duration < self.timer_shortest_duration:
            self.timer_shortest_duration = duration

        if self.timer_longest_duration < duration:
            self.timer_longest_duration = duration

        self.calculate_timer_average_duration()
        self.trim_timer_duration_list()

    def trim_timer_duration_list(self):
        if len(self.timer_duration_list) > self.timer_duration_list_max:
            del self.timer_duration_list[self.timer_duration_list_max:]


