"""

Ankerinfo / -alarm

Daten
  - Position des Ankers
  - Wassertiefe beim Ankern
  - Gesteckte Kettenlänge
  - aktuelle Position des Schiffs
  - aktuelle Wassertiefe an Schiffsposition
  - aktuelle Schiffsausrichtung bearing/heading
  - aktuelle Windrichtung (wahr)
  - aktuelle Windstärke (wahr)
  - Alarm aktiv J/N
  - Alarmradius
  - GPS Abweichung/ Fehler in der Horizontalen
  - Zeitpunkt des Ankeraus

Darstellung:
  - Modi: Normal / Konfiguration
  - Anker oben / unten
  - Nord ist oben 

Es gibt verschiedene Unterseiten
  - Normalansicht
  - Konfigurationsseite

"""

import os
import cairo
import math
import time
from cfgmenu import Menu
from .page import Page

class Anchor(Page):

    def __init__(self, pageno, cfg, appdata, boatdata):
        super().__init__(pageno, cfg, appdata, boatdata)
        self.sym_anchor = cairo.ImageSurface.create_from_png(os.path.join(cfg['imgpath'], "anchor.png"))
        self.buttonlabel[1] = 'MODE'
        self.buttonlabel[2] = 'DROP'
        self.buttonlabel[5] = '' # ALARM erst möglich wenn der Anker unten ist

        self.mode = 'N' # (N)ormal, (C)onfiguration
        self.scale = 50 # Radius of display circle in meter

        self._bd = boatdata

        # Der sinnvolle Abstand ist abhängig von der Länge der gesteckten Kette
        # Die initial eingegebene Position des Ankers sollte nactträglich justiert
        # werden können

        self.chain_length = 60 # maximale Länge die ausgesteckt werden kann
        self.chain = 35 # aktuell gesteckte Länge
        self.anchor_set = False
        self.anchor_lat = 0
        self.anchor_lon = 0
        self.anchor_depth = -1
        self.anchor_ts = None # Timestamp of dropped anchor
        self.lat = 0
        self.lon = 0
        self.heading = -1
        self.depth = -1
        self.alarm_range = 20
        self.alarm_enabled = False
        self.alarm = False # Alarm ist ausgelöst und aktiv
        self.wind_angle = -1

        # Menüsteuerung für Konfiguration
        self._menu = Menu("Options", 20, 80)
        self._menu.setItemDimension(120, 20)
        newitem = self._menu.addItem("chain", "Chain out", "int", 0, "m")
        newitem.setRange(0, 200, (1, 5, 10))
        newitem = self._menu.addItem("chainmax", "Chain max", "int", self.chain_length, "m")
        newitem.setRange(0, 200, (1, 5, 10))
        newitem = self._menu.addItem("zoom", "Zoom", "int", 2)
        newitem.setRange(1, 8, (1,))
        newitem = self._menu.addItem("range", "Alarm range", "int", 40, "m")
        newitem.setRange(1, 200, (1, 5, 10))
        self._menu.setItemActive("chain")

        self._test = 0

    def handle_key(self, buttonid):
        if buttonid == 1:
            if self.mode == 'N':
                self.mode = 'C'
                self.buttonlabel[2] = '#UP'
                self.buttonlabel[3] = '#DOWN'
                itm = self._menu.getActiveItem()
                stepwidth = itm.steps[itm.step]
                self.buttonlabel[4] = f"-{stepwidth}"
                self.buttonlabel[5] = f"+{stepwidth}"
                self.buttonlabel[6] = 'STEP'
            else:
                self.mode = 'N'
                self.buttonlabel[2] = 'RISE' if self.anchor_set else 'DROP'
                self.buttonlabel[3] = '#PREV'
                self.buttonlabel[4] = '#NEXT'
                self.buttonlabel[5] = 'ALARM' if not self.alarm_enabled else 'OFF'
            return True
        if self.mode == 'N':
            # Normal
            if buttonid == 2:
                if not self.anchor_set:
                    self.anchor_lat = self._bd.lat
                    self.anchor_lon = self._bd.lon
                    self.anchor_set = True
                    self.anchor_ts = time.time()
                    self.buttonlabel[2] = 'RISE'
                    self.buttonlabel[5] = 'ALARM'
                else:
                    self.anchor_set = False
                    self.alarm = False
                    self.alarm_enabled = False
                    self.anchor_ts = None
                    self.buttonlabel[2] = 'DROP'
                    self.buttonlabel[5] = ''
                return True
            elif buttonid == 5:
                # Bei aktivem Alarm kann mit dieser Taste der Alarm zurückgesetzt
                # werden. Die Tastenbeschriftung wechselt zwischen ALARM und OFF.
                if self.alarm:
                    self.alarm = False
                    self.buttonlabel[5] = 'ALARM'
                if self.alarm_enabled:
                    self.alarm_enabled = False
                    self.buttonlabel[5] = 'ALARM'
                else:
                    self.alarm_enabled = True
                    self.buttonlabel[5] = 'OFF'
                return True
        else:
            # Konfiguration
            itm = self._menu.getActiveItem()
            if buttonid == 2:
                if self._menu.activeitem == 0:
                    self._menu.activeitem = self._menu.getItemCount() - 1
                else:
                    self._menu.activeitem -= 1
            elif buttonid == 3:
                if self._menu.activeitem == self._menu.getItemCount() - 1:
                    self._menu.activeitem = 0
                else:
                    self._menu.activeitem += 1
            elif buttonid == 4:
                # decrease value by step
                stepwidth = itm.steps[itm.step]
                itm.setValue(itm.value - stepwidth)
            elif buttonid == 5:
                # increase value by step
                stepwidth = itm.steps[itm.step]
                itm.setValue(itm.value + stepwidth)
            elif buttonid == 6:
                ns = len(itm.steps)
                if ns > 1:
                    if itm.step < ns - 1:
                        itm.step += 1
                    else:
                        itm.step = 0
            stepwidth = itm.steps[itm.step]
            self.buttonlabel[4] = f"-{stepwidth}"
            self.buttonlabel[5] = f"+{stepwidth}"
            return True
        return False

    def draw_normal(self, ctx):

        """
        value1 = LAT
        value2 = LON
        value3 = HDOP
        value4 = DBS
        value5 = TWD
        value6 = TWS
        """

        # self.anchor_lat =

        # Name
        ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
        ctx.set_font_size(20)

        ctx.move_to(2, 50)
        ctx.show_text("Anchor")
        ctx.move_to(2, 200)
        ctx.show_text("Depth")
        ctx.move_to(320, 50)
        ctx.show_text("Chain")

        ctx.set_font_size(16)
        ctx.move_to(2, 70)
        ctx.show_text("Alarm: ")
        if self.alarm_enabled:
            ctx.show_text("On")
        else:
            ctx.show_text("Off")
        ctx.move_to(320, 70)
        ctx.show_text(f"{self.chain} m")

        ctx.move_to(10, 220)
        if self._bd.dbs.valid:
            ctx.show_text(self._bd.dbs.format())

        ctx.stroke()

        # Spezialseite
        cx = 200
        cy = 150
        r = 125

        # Skala
        ctx.set_line_width(1)
        ctx.arc(cx, cy, r, 0, 2*math.pi)
        ctx.move_to(cx + 10, cy + 0.5)
        ctx.line_to(cx + r - 4, cy + 0.5)
        ctx.move_to(cx + r / 2, cy + 20)
        # Pfeil links
        ctx.move_to(cx + 10, cy + 0.5)
        ctx.line_to(cx + 16, cy - 4 + 0.5)
        ctx.move_to(cx + 10, cy + 0.5)
        ctx.line_to(cx + 16, cy + 4 + 0.5)
        # Pfeil rechts
        ctx.move_to(cx + r - 4, cy + 0.5)
        ctx.line_to(cx + r - 10, cy - 4 + 0.5)
        ctx.move_to(cx + r - 4, cy + 0.5)
        ctx.line_to(cx + r - 10, cy + 4 + 0.5)

        ctx.set_font_size(16)
        self.draw_text_center(ctx, cx + r / 2, cy + 8, str(self.scale) + " m")
        ctx.stroke()

        ctx.set_line_width(1.5)
        # Ankersymbol falls Anker fallen gelassen wurde
        # Ansonsten ist das Boot-Symbol im Mittelpunkt
        if self.anchor_set:
            ctx.save()
            ctx.set_source_surface(self.sym_anchor, cx-8, cy-8)
            ctx.paint()
            ctx.restore()

        # Boot zeichnen
        # Heading beachten
        # Wir arbeiten mit einer Kopie, weil bx/by im Laufe der Zeit von
        # cx/cy abweichen werden
        if self.anchor_set:
            bx = cx
            by = cy + 30
        else:
            bx = cx  
            by = cy + 8
        p = ((bx - 5, by), (bx - 5, by - 10), (bx, by - 16), (bx + 5, by - 10), (bx + 5, by), (bx - 6, by))
        if self._bd.hdt.value:
            # Rotiere Boot-Symbol um eigenes Zentrum
            boat = self.rotate((bx, by - 8), p, self._bd.hdt.value)
        else:
            # Kein Heading, Boot immer zeichnen
            boat = p
        ctx.move_to(*boat[0])
        for point in boat[1:]:
            ctx.line_to(*point)
        ctx.stroke()

        # Windpfeil zeichnen
        if self._bd.awa.value:
            p = ((cx, cy - r + 25), (cx - 12, cy - r - 4), (cx, cy - r + 6), (cx + 12, cy - r - 4), (cx, cy - r + 25))
            wind = self.rotate((cx, cy), p, self._bd.awa.value)
            ctx.move_to(*wind[0])
            for point in wind[1:]:
                ctx.line_to(*point)
            ctx.fill()

    def draw_config(self, ctx):
        ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
        ctx.set_font_size(20)

        ctx.move_to(2, 50)
        ctx.show_text("Anchor configuration")

        # Menü zeichnen
        ctx.save()
        ctx.set_font_size(16)
        x, y, w, h = self._menu.getRect()
        ctx.set_line_width(1)
        x += 0.5 # Cairo-Fix for single pixel line
        y += 0.5
        ctx.save()
        ctx.rectangle(x, y, w, h)
        ctx.clip_preserve()
        ctx.stroke()
        for m in self._menu:
            ix, iy, iw, ih = self._menu.getItemRect(m.position)
            inverted = (m.position == self._menu.activeitem)
            self.draw_text_boxed(ctx, ix, iy, iw, ih, m.label, inverted, False)
        ctx.stroke()
        # Werte neben dem Menü
        ctx.restore()
        ctx.rectangle(0, 20, 400, 360) # new clipping
        ctx.clip()
        self._test += 1
        for m in self._menu:
            ix, iy, iw, ih = self._menu.getItemRect(m.position)
            ctx.move_to(ix + iw + 20, iy + ih - 4) # 5 für Unterlängen
            ctx.show_text(f"{m.value} {m.unit}")
        ctx.stroke()
        ctx.restore()

    def draw(self, ctx):
        if self.mode == 'N':
            self.draw_normal(ctx)
        else:
            self.draw_config(ctx)
        if self._bd.alarm:
            self.draw_alarm(ctx, self._bd.alarm_src, self._bd.alarm_id, self._bd.alarm_msg)
