import os
import platform
import pygame
import time
import math

import configparser

import paho.mqtt.client as mqtt
from DataObject import DataObject

from Screen import Screen
from elements.Text import Text, VariableText
from elements.Textbox import Textbox
from elements.Compass import OuterNeedle
from elements.Line import draw_dashed_line, Point

topic = ""

def on_connect(client, userdata, flags, rc):
    print("Subscribe to {}".format(topic))
    client.subscribe(topic)


def splashscreen(screen, fadein, solid, fadeout, font_size):
    screen.background("white")
    size = screen.getSize()
    txt = Text("powered by NetWEB Systems", font_size)
    img = pygame.image.load("resources/NWS.bmp")
    imgSize = img.get_rect().size
    surface = pygame.Surface(size)
    surface.fill(pygame.Color("white"))
    surface.blit(img, (size[0]//2 - imgSize[0], size[1]//2 - imgSize[1]))
    surface.blit(txt.get(), (size[0]//2, size[1]//2))

    if (fadein > 0):
        for alpha in range(0,255): #0 is transparent, 255 is opaque
            screen.reset()
            surface.set_alpha(alpha)
            screen.blit(surface,0,0)
            screen.update()
            time.sleep( fadein/255 )
    
    screen.reset()
    screen.blit(surface,0,0)
    screen.update()
    time.sleep(solid)

    if (fadeout > 0):
        for alpha in range(0,255): #0 is transparent, 255 is opaque
            screen.reset()
            surface.set_alpha(255-alpha)
            screen.blit(surface,0,0)
            screen.update()
            time.sleep( fadeout/255 )

def getPos(angle, radius, offset):
    return ( int( radius * math.cos(angle) )+offset, int( radius * math.sin(angle) )+offset)

def blitRotate(surf, image, pos, originPos, angle):

    # calcaulate the axis aligned bounding box of the rotated image
    w, h       = image.get_size()
    box        = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]
    box_rotate = [p.rotate(angle) for p in box]
    min_box    = (min(box_rotate, key=lambda p: p[0])[0], min(box_rotate, key=lambda p: p[1])[1])
    max_box    = (max(box_rotate, key=lambda p: p[0])[0], max(box_rotate, key=lambda p: p[1])[1])

    # calculate the translation of the pivot 
    pivot        = pygame.math.Vector2(originPos[0], -originPos[1])
    pivot_rotate = pivot.rotate(angle)
    pivot_move   = pivot_rotate - pivot

    # calculate the upper left origin of the rotated image
    origin = (pos[0] - originPos[0] + min_box[0] - pivot_move[0], pos[1] - originPos[1] - max_box[1] + pivot_move[1])

    # get a rotated image
    rotated_image = pygame.transform.rotate(image, angle)

    # rotate and blit the image
    surf.blit(rotated_image, origin)

def buildBackground( size, config ):
    surface = pygame.Surface( size, pygame.SRCALPHA)

    w = size[0]
    h = size[1]

    try:
        dashedLineColor = pygame.Color( config.get('CompassBackground','dashedLineColor') )
    except:
        dashedLineColor = pygame.Color("Black")

    try:
        groundColor = pygame.Color( config.get('CompassBackground','groundColor'))
    except:
        groundColor = pygame.Color("Black")

    radius = min( w, h ) // 2
    angle = config.getint('CompassBackground', 'angleOffset')
    angle = math.radians( angle )

    dash_length = config.getint('CompassBackground','dashSize')

    #Kaimauer
    start = getPos( angle, radius, offset=radius )
    end = getPos( angle+math.pi, radius, offset=radius )
    draw_dashed_line(surface, dashedLineColor, start, end, width=2, dash_length= dash_length )

    alpha = 2 * math.acos( 1-( (radius-10)/radius ) )
    start = getPos( (math.pi/2) + (alpha/2) + angle, radius, offset=radius )
    end = getPos( (math.pi/2) - (alpha/2) + angle, radius, offset=radius )
    draw_dashed_line(surface, dashedLineColor, start, end, width=2, dash_length= dash_length )

    start = getPos( angle+(math.pi/2), radius//10*8, offset=radius )
    end = getPos( angle+(math.pi/2), radius//10*1, offset=radius )

    #x1 = Point( start )
    #x2 = Point( end )
    #alpha = math.radians(20)
    #d = len(x1 - x2)
    #print(d)
    #length = d * (1/math.sin(math.pi+alpha)) 
    #print(length)
    #x = d * math.cos( alpha )
    #y = d * math.cos( alpha )
    #print( x, y)
    #pygame.draw.line( surface, groundColor, start, (x,y) )

    txt = Text( 'Terminal', 20 )
    txt.setColor('Lightgrey')
    txt_surface = pygame.transform.rotate( txt.get(), -math.degrees(angle) )
    pos = getPos(angle+(math.pi/2), radius/10*2, radius-txt.getWidth()//2)
    surface.blit( txt_surface, pos )

    #circle_surface = pygame.Surface( size, pygame.SRCALPHA)
    #pygame.draw.circle( circle_surface, groundColor, (w//2, h//2), radius, width=0, draw_bottom_left=True)
    #pygame.draw.circle( circle_surface, groundColor, (w//2, h//2), radius, width=0, draw_bottom_right=True)
    #blitRotate(surface, circle_surface, (w//2,h//2), (w//2,h//2), -math.degrees(angle))

    return surface

if  __name__ == "__main__":

    #load config
    config = configparser.ConfigParser()
    config.read("config.ini")

    fullscreen = config.getboolean('General', 'fullscreen')
    timeToEnd = config.getfloat('General','timetoend')

    screen = Screen(800,480, fullscreen)
    screen.setCaption("Windmessanlage")
    screen.background("white")

    #Splashscreen
    splashscreen(screen, config.getfloat('Splashscreen','fadein'), config.getfloat('Splashscreen','solid'), config.getfloat('Splashscreen','fadeout'), config.getint('Splashscreen','font_size'))

    #-average speed 2min
    size = ( int(config.get('AVG2Speed','width')), int(config.get('AVG2Speed','height')) )
    x = int(config.get('AVG2Speed','x'))
    y = int(config.get('AVG2Speed','y'))
    averageSpeed2 = Textbox( size, x, y, int(config.get('AVG2Speed','font_size')) )
    averageSpeed2.setText("Ø 2min:\n{}m/s")
    averageSpeed2.setBackgroundColor("Black")

    #-average speed 10min
    size = ( int(config.get('AVG10Speed','width')), int(config.get('AVG10Speed','height')) )
    x = int(config.get('AVG10Speed','x'))
    y = int(config.get('AVG10Speed','y'))
    averageSpeed10 = Textbox( size, x, y, int(config.get('AVG10Speed','font_size')) )
    averageSpeed10.setText("\nØ 10min:\n{}m/s")
    averageSpeed10.setBackgroundColor("Black")

    #-max speed 2min
    size = ( int(config.get('Max2Speed','width')), int(config.get('Max2Speed','height')) )
    x = int(config.get('Max2Speed','x'))
    y = int(config.get('Max2Speed','y'))
    maxSpeed2 = Textbox( size, x, y, int(config.get('Max2Speed','font_size')) )
    maxSpeed2.setText("Max 2min:\n{}m/s")
    maxSpeed2.setBackgroundColor("black")


    #-max speed 10min
    size = ( int(config.get('Max10Speed','width')), int(config.get('Max10Speed','height')) )
    x = int(config.get('Max10Speed','x'))
    y = int(config.get('Max10Speed','y'))
    maxSpeed10 = Textbox( size, x, y, int(config.get('Max10Speed','font_size')) )
    maxSpeed10.setText("\nMax 10min:\n{}m/s")
    maxSpeed10.setBackgroundColor("Black")

    #compass
    compass = OuterNeedle(int(config.get('Compass','font_size')), (int(config.get('Compass','width')), int(config.get('Compass','height'))) )
    compass.setX( int(config.get('Compass','x')) )
    compass.setY( int(config.get('Compass','y')) )
    compass.setBackgroundColor( config.get('Compass', 'background') )
    compass.setNeedleColor( config.get('Compass', 'needle_color') )
    compass.setLineLength( config.getint('Compass', 'lineLength') )

    compass.setBackgroundSurface( buildBackground( (int(config.get('Compass','width')), int(config.get('Compass','height'))), config  ) )

    #-Current speed
    currentSpeed = VariableText("", int(config.get('CurrentSpeed','font_size')))
    currentSpeed.setX(int(config.get('CurrentSpeed','x')))
    currentSpeed.setY(int(config.get('CurrentSpeed','y')))
    currentSpeed.setUnit("m/s")
    currentSpeed.setColor("white")

    #MQTT
    topic = config.get('MQTT','topic')
    mqttc = mqtt.Client()
    mqttc.on_connect = on_connect

    data = DataObject()
    mqttc.message_callback_add( config.get('MQTT','topic'), data.data)
    mqttc.message_callback_add( config.get('MQTT','config'), data.config)

    mqtt_host = config.get('MQTT', 'host')
    mqtt_port = int(config.get('MQTT', 'port'))


    screen.reset()
    screen.blit( Text("Try to connect to MQTT server", 24).get(), 0, 0)
    screen.blit( Text("Server: {0}:{1}".format(mqtt_host, mqtt_port),24).get(), 0, 25)
    screen.update()
    pygame.mouse.set_visible(False)

    while(True):
        try:
            mqttc.connect(mqtt_host, port=mqtt_port, keepalive=int(config.get('MQTT', 'keepalive')))
            break
        except (KeyboardInterrupt, SystemExit):
            print("KeyboardInterrupt or SystemExit")
            raise
        except:
            time.sleep(3)
            print("Try to reconnect")
    mqttc.loop_start()


    #limit framerate
    clock = pygame.time.Clock()
    time_start = 0

    while True:
        e = pygame.event.poll()
        if e.type == pygame.QUIT:
            break

        if e.type == pygame.MOUSEBUTTONDOWN:
            time_start = time.time()

        if e.type == pygame.MOUSEBUTTONUP:
            if (time.time() - time_start > timeToEnd):
                print("{}s".format(time.time() - time_start))
                break



        screen.reset()
        currentSpeed.update(data.currentSpeed)
        averageSpeed2.update(data.speed2AVG)
        averageSpeed10.update(data.speed2AVG)
        maxSpeed2.update(data.speed2Max)
        maxSpeed10.update(data.speed10Max)
        compass.update(data.compass)


        screen.blit( averageSpeed2.get(), averageSpeed2.getX(), averageSpeed2.getY() )
        screen.blit( averageSpeed10.get(), averageSpeed10.getX(), averageSpeed10.getY() )
        screen.blit( maxSpeed2.get(), maxSpeed2.getX(), maxSpeed2.getY() )
        screen.blit( maxSpeed10.get(), maxSpeed10.getX(), maxSpeed10.getY() )
        screen.blit( compass.get(), compass.getX(), compass.getY() )
        screen.blit( currentSpeed.get(), currentSpeed.getX(), currentSpeed.getY() )
        screen.update()

        #Limit to 30 fps
        clock.tick(30)
    

    screen.quit()
