#!/usr/bin python3
# -*- coding: utf-8 -*-
"""
This project is designed for the WaveShare 12.48" eInk display. Modifications will be needed for other displays,
especially the display drivers and how the image is being rendered on the display. Also, this is the first project that
I posted on GitHub so please go easy on me. There are still many parts of the code (especially with timezone
conversions) that are not tested comprehensively, since my calendar/events are largely based on the timezone I'm in.
There will also be work needed to adjust the calendar rendering for different screen sizes, such as modifying of the
CSS stylesheets in the "render" folder.
"""
import datetime as dt
import os
import sys
import locale


import json
import logging
from PIL import Image,ImageDraw,ImageFont

from cal.cal import CalendarHelper
from weather.weather import WeatherHelper


def main():
    # Basic configuration settings (user replaceable)
    # config.json is in the root folder
    configFile = open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'config.json'))
    config = json.load(configFile)


    isDisplayConected = config['isDisplayConected']  # set to true when debugging rendering without displaying to screen
    
    screenWidth       = config['screenWidth']  # Width of E-Ink display. Default is landscape. Need to rotate image to fit.
    screenHeight      = config['screenHeight']  # Height of E-Ink display. Default is landscape. Need to rotate image to fit.
    imageWidth        = config['imageWidth']  # Width of image to be generated for display.
    imageHeight       = config['imageHeight'] # Height of image to be generated for display.
    rotateAngle       = config['rotateAngle']  # If image is rendered in portrait orientation, angle to rotate to fit screen
    
    hourFormat        = config['hourFormat'] # The format the hour will be displayed. eg. 13:02 or 01:02 PM
    
    latitude          = config['latitude'] # A float. The latitude for the Weather API.
    longitude         = config['longitude'] # A float. The longitude for the Weather API.
    timezone          = config['timezone'] # The timezone is necesary for the Weather API
    locales           = config['locales'] # Set the locales for the month name

    caldavURL         = config['caldavURL'] # URL to Caldav calendar. eg. 'https://nextcloud.example/remote.php/dav'
    caldavUser        = config['caldavUser'] # Caldav username
    caldavPassword    = config['caldavPassword'] # Caldav password
    caldavBlacklist   = config ['caldavBlacklist'] # Caldav list of calendars to be ommited
    # Convert json "str1, str2" to a python list
    caldavBlacklist = caldavBlacklist.split(',')
    for i in range(len(caldavBlacklist)):
        caldavBlacklist[i-1] = caldavBlacklist[i-1].strip()


    locale.setlocale(locale.LC_TIME, locales)
    
    # Set the hour, this is important to see what time the e-Paper has been syncronized
    if hourFormat == "12h":
        time = dt.datetime.now().strftime("%I:%M %p")   
    else:
        time = dt.datetime.now().strftime("%H:%M")

    day = dt.datetime.now().strftime("%A, %d %b")
    tomorrow = dt.datetime.now() + dt.timedelta(days=1)
    tomorrow = dt.datetime.strftime(tomorrow, "%A, %d %b")


    assets = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'assets')
    weather_icons = os.path.join(assets, 'weather-icons')
    fonts = os.path.join(assets, 'fonts')
    # Drawing on the image
    font8 = ImageFont.truetype(os.path.join(os.path.join(fonts, 'pixel_operator'), 'PixelOperator8.ttf'), 8)
    font16 = ImageFont.truetype(os.path.join(os.path.join(fonts, 'pixel_operator'), 'PixelOperator.ttf'), 16)
    font16_bold = ImageFont.truetype(os.path.join(os.path.join(fonts, 'pixel_operator'), 'PixelOperator-Bold.ttf'), 16)



    image = Image.new('1', (imageWidth, imageHeight), 255)  # 255: clear the frame    
    draw = ImageDraw.Draw(image)

    # Draw todays date
    draw.text((0, 0), f"{day}. {time}", font = font16_bold, fill = 0) # draw the current time in the top left corner

    # Frames
    draw.line([(0,16),(250,16)], fill = 0,width = 2) # Draw a line below the date
    draw.line([(90,17),(90,122)], fill = 0,width = 2) # Line dividing the screeen in two parts


    # Calendar icon
    cal_coordinates_x = 207
    cal_coordinates_y = 2
    cal_icon = Image.open(os.path.join(assets, "cal-icon3.bmp")) # calendar icon
    # This seems complicates, but it just draw a white rectangle bellow the calendar
    draw.rectangle([(cal_coordinates_x-2, cal_coordinates_y),(cal_coordinates_x + 28, cal_coordinates_y + 30)], fill = 255)
    image.paste(cal_icon, (cal_coordinates_x, cal_coordinates_y))

    # LEFT SEGMENT (WEATHER)
    try:
        # Todays information
        weatherService = WeatherHelper(latitude, longitude, timezone)

        weather_data = weatherService.fetch_open_meteo_data()
        today_icon = weatherService.iconize_weather(weather_data["current_weather_code"])
        today_icon = Image.open(os.path.join(weather_icons, today_icon))
        image.paste(today_icon, (29,20))

        today_temperature = f"{str(weather_data['current_temperature_2m'])}°"
        draw.text((66,28), today_temperature, font = font16_bold, fill = 0) # The tomorrows temperature is bellow the icon


        #draw.text((160, 26), 'Agenda', font = font16_bold, fill = 0)

        # All the tomorrows information
        tomorrow_icon = weatherService.iconize_weather(weather_data["tomorrow_weather_code"])
        tomorrow_icon = Image.open(os.path.join(weather_icons, tomorrow_icon))
        image.paste(tomorrow_icon, (6,74)) # The icon is in the bottom left corner

        tomorrow_temperature = f"{str(weather_data['tomorrow_temperature_2m_max'])}/{str(weather_data['tomorrow_temperature_2m_min'])}°"
        draw.text((6,106), tomorrow_temperature, font = font16_bold, fill = 0) # The tomorrows temperature is bellow the icon

        # All the day after tomorrows information
        day_after_icon = weatherService.iconize_weather(weather_data["day_after_weather_code"])
        day_after_icon = Image.open(os.path.join(weather_icons, day_after_icon))
        image.paste(day_after_icon, (52,74))

        day_after_temperature = f"{str(weather_data['day_after_temperature_2m_max'])}/{str(weather_data['day_after_temperature_2m_min'])}°"
        draw.text((52,106), day_after_temperature, font = font16_bold, fill = 0)
    except:
        pass
        # TODO: desing an error icon and

    # RIGHT SEGMENT (CALENDAR/AGENDA)
    try:
        calService = CalendarHelper(caldavURL, caldavUser, caldavPassword, timezone=timezone, caldavBlacklist=caldavBlacklist)
        calendar_data = calService.fetch_cals()
        #print(calendar_data)

        last_date: str = None
        max_agenda_lines = 7
        agenda_lines = 0

        agenda_x = 96
        agenda_y = 16
        font_size = 13

        for event in calendar_data:
            text: str = ''
            bold: bool = False

            event_date = dt.datetime.strftime(event["DTSTART"], "%A, %d %b")
            if event_date != last_date:

                last_date = event_date
                # check if date is today or tomorrow
                if last_date == day:
                    text = "Hoy"
                    bold = True
                elif last_date == tomorrow:
                    text = "Mañana"
                    bold = True
                else:
                    text = last_date
                    bold = True
                
                coords_y = font_size * agenda_lines + agenda_y
                if coords_y >= screenHeight - font_size*2:
                    break
                draw.text((agenda_x, coords_y), text, font = font16_bold, fill = 0)
                agenda_lines += 1
                last_date = event_date

            text = f'-{event["SUMMARY"]}'
            
            coords_y = font_size * agenda_lines + agenda_y
            if coords_y >= screenHeight - font_size:
                break
            draw.text((agenda_x, coords_y), text, font = font16, fill = 0)
            agenda_lines += 1
            
    except:
        pass
    # TODO: clean the code and comment

    # draw.line([(0,50),(50,0)], fill = 0,width = 1)
    # draw.chord((10, 60, 50, 100), 0, 360, fill = 0)
    # draw.ellipse((55, 60, 95, 100), outline = 0)
    # draw.pieslice((55, 60, 95, 100), 90, 180, outline = 0)
    # draw.pieslice((55, 60, 95, 100), 270, 360, fill = 0)
    # draw.polygon([(110,0),(110,50),(150,25)],outline = 0)
    # draw.polygon([(190,0),(190,50),(150,25)],fill = 0)
    # draw.rectangle([(0,0),(50,50)],outline = 0)

    image.save(os.path.join(assets, 'output.bmp'))


    if isDisplayConected:
        from display.display import DisplayHelper

        displayService = DisplayHelper(screenWidth, screenHeight)
        displayService.update(image.rotate(rotateAngle)) # Displays the image
        #displayService.clear()
        displayService.sleep()  # go to sleep


if __name__ == "__main__":
    main()
