#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
Calendar module for Inky-Calendar Project
Copyright by aceisace
"""
from __future__ import print_function
import calendar
from configuration import *
from settings import *
import arrow
from PIL import Image, ImageDraw

print_events = False
show_events = True
max_event_lines = 4
style = "DD MMM"
event_icon = 'square' # dot #square

if show_events == True:
  from inkycal_icalendar import fetch_events

"""Add a border to increase readability"""
border_top = int(middle_section_height * 0.02)
border_left = int(middle_section_width * 0.02)

main_area_height = middle_section_height-border_top*2
main_area_width = middle_section_width-border_left*2

"""Calculate height for each sub-section"""
month_name_height = int(main_area_height*0.1)
weekdays_height = int(main_area_height*0.05)
calendar_height = int(main_area_height*0.6)
events_height = int(main_area_height*0.25)

"""Set rows and coloumns in the calendar section and calculate sizes"""
calendar_rows, calendar_coloumns = 6, 7
icon_width = main_area_width // calendar_coloumns
icon_height = calendar_height // calendar_rows

"""Calculate paddings for calendar section"""
x_padding_calendar = int((main_area_width % icon_width) / 2)
y_padding_calendar = int((main_area_height % calendar_rows) / 2)

"""Add coordinates for number icons inside the calendar section"""
grid_start_y = (middle_section_offset + border_top + month_name_height +
                weekdays_height + y_padding_calendar)
grid_start_x = border_left + x_padding_calendar

grid = [(grid_start_x + icon_width*x, grid_start_y + icon_height*y)
        for y in range(calendar_rows) for x in range(calendar_coloumns)]

weekday_pos = [(grid_start_x + icon_width*_, middle_section_offset +
                month_name_height) for _ in range(calendar_coloumns)]

event_lines = [(border_left,(bottom_section_offset - events_height)+
                int(events_height/max_event_lines*_)) for _ in
               range(max_event_lines)]

def main():
  try:
    clear_image('middle_section')
    print('Calendar module: Generating image...', end = '')
    now = arrow.now(tz = get_tz())

    """Set up the Calendar template based on personal preferences"""
    if week_starts_on == "Monday":
      calendar.setfirstweekday(calendar.MONDAY)
      weekstart = now.replace(days = - now.weekday())
    else:
      calendar.setfirstweekday(calendar.SUNDAY)
      weekstart = now.replace(days = - now.isoweekday())

    """Write the name of the current month at the correct position"""
    write_text(main_area_width, month_name_height,
      str(now.format('MMMM',locale=language)), (border_left,
      middle_section_offset), autofit = True)

    """Set up weeknames in local language and add to main section"""
    weekday_names = [weekstart.replace(days=+_).format('ddd',locale=language)
      for _ in range(7)]

    for _ in range(len(weekday_pos)):
      write_text(icon_width, weekdays_height, weekday_names[_],
                 weekday_pos[_], autofit = True)

    """Create a calendar template and flatten (remove nestings)"""
    flatten = lambda z: [x for y in z for x in y]
    calendar_flat = flatten(calendar.monthcalendar(now.year, now.month))

    """Add the numbers on the correct positions"""
    for i in range(len(calendar_flat)):
      if calendar_flat[i] != 0:
        write_text(icon_width, icon_height, str(calendar_flat[i]), grid[i])

    """Draw a red/black circle with the current day of month in white"""
    icon = Image.new('RGBA', (icon_width, icon_height))
    current_day_pos = grid[calendar_flat.index(now.day)]
    x_circle,y_circle = int(icon_width/2), int(icon_height/2)
    radius = int(icon_width * 0.25)
    text_width, text_height = default.getsize(str(now.day))
    x_text = int((icon_width / 2) - (text_width / 2))
    y_text = int((icon_height / 2) - (text_height / 1.7))
    ImageDraw.Draw(icon).ellipse((x_circle-radius, y_circle-radius,
      x_circle+radius, y_circle+radius), fill= 'red' if
      display_type == 'colour' else 'black', outline=None)
    ImageDraw.Draw(icon).text((x_text, y_text), str(now.day), fill='white',
      font=bold)
    image.paste(icon, current_day_pos, icon)

    """Create some reference points for the current month"""
    days_current_month = calendar.monthrange(now.year, now.month)[1]
    month_start = now.replace(days =-now.day+1)
    month_end = now.replace(days=+(days_current_month-now.day))

    if show_events == True:
      """Filter events which begin before the end of this month"""
      upcoming_events = fetch_events()

      calendar_events = [events for events in upcoming_events if
        events.begin < month_end and events.begin.month == now.month]

      """Find days with events in the current month"""
      days_with_events = []
      for events in calendar_events:
        if events.duration.days <= 1:
          days_with_events.append(int(events.begin.format('D')))
        else:
          for day in range(events.duration.days):
            days_with_events.append(
              int(events.begin.replace(days=+i).format('D')))
      days_with_events = set(days_with_events)

      if event_icon == 'dot':
        for days in days_with_events:
          write_text(icon_width, int(icon_height * 0.2), '•',
            (grid[calendar_flat.index(days)][0],
             int(grid[calendar_flat.index(days)][1] + icon_height*0.8)))

      if event_icon == 'square':
        square_size = int(icon_width *0.6)
        center_x = int((icon_width - square_size) / 2)
        center_y = int((icon_height - square_size) / 2)
        for days in days_with_events:
          draw_square((int(grid[calendar_flat.index(days)][0]+center_x),
             int(grid[calendar_flat.index(days)][1] + center_y )),
             8, square_size , square_size)


      """Add a small section showing events of today and tomorrow"""
      event_list = ['{0} at {1} : {2}'.format('today', event.begin.format(
        'HH:mm' if hours == 24 else 'hh:mm'), event.name)
        for event in calendar_events if event.begin.day == now.day]
      
      event_list += ['{0} at {1} : {2}'.format('tomorrow', event.begin.format(
        'HH:mm' if hours == 24 else 'hh:mm'), event.name)
        for event in calendar_events if event.begin.day == now.replace(days=+1).day]

      del event_list[4:]

    if event_list:
      for lines in event_list:
        write_text(main_area_width, int(events_height/max_event_lines), lines,
          event_lines[event_list.index(lines)], alignment='left',
          fill_height = 0.7)
    else:
      write_text(main_area_width, int(events_height/max_event_lines),
       'No events today or tomorrow', event_lines[0], alignment='left',
       fill_height = 0.7)

    """Set print_events_to True to print all events in this month"""
    style = 'DD MMM YY HH:mm'
    if print_events == True and calendar_events:
      line_width = max(len(_.name) for _ in calendar_events)
      for events in calendar_events:
        print('{0} {1} | {2} | {3} | All day ='.format(events.name,
          ' ' * (line_width - len(events.name)), events.begin.format(style),
          events.end.format(style)), events.all_day)

    calendar_image = crop_image(image, 'middle_section')
    calendar_image.save(image_path+'calendar.png')

    print('Done')

  except Exception as e:
    """If something went wrong, print a Error message on the Terminal"""
    print('Failed!')
    print('Error in Calendar module!')
    print('Reason: ',e)
    pass


if __name__ == '__main__':
  main()