"""CW Decoder.

Sammelt die von der 'CW Element Tagger'-Stufe erzeugten Punkt-/Strich-Tags
pro Zeichen und decodiert bei einer Zeichen- oder Wortpause ueber die
internationale Morsecode-Tabelle. Publiziert den fortlaufend decodierten
Text als PMT-Message - analog zum DCF77-Decoder-Block.
"""
import numpy as np
from gnuradio import gr
import pmt

MORSE_TO_CHAR = {
    '.-': 'A', '-...': 'B', '-.-.': 'C', '-..': 'D', '.': 'E', '..-.': 'F',
    '--.': 'G', '....': 'H', '..': 'I', '.---': 'J', '-.-': 'K', '.-..': 'L',
    '--': 'M', '-.': 'N', '---': 'O', '.--.': 'P', '--.-': 'Q', '.-.': 'R',
    '...': 'S', '-': 'T', '..-': 'U', '...-': 'V', '.--': 'W', '-..-': 'X',
    '-.--': 'Y', '--..': 'Z',
    '-----': '0', '.----': '1', '..---': '2', '...--': '3', '....-': '4',
    '.....': '5', '-....': '6', '--...': '7', '---..': '8', '----.': '9',
}


class blk(gr.sync_block):
    def __init__(self):
        gr.sync_block.__init__(
            self, name="CW Decoder",
            in_sig=[np.float32], out_sig=None)
        self.current = ""
        self.text = ""
        self.message_port_register_out(pmt.intern("out"))

    def work(self, input_items, output_items):
        in0 = input_items[0]
        tags = self.get_tags_in_window(0, 0, len(in0))

        for tag in tags:
            key = pmt.to_python(tag.key)
            val = pmt.to_python(tag.value)

            if key == "cw_symbol":
                self.current += val
            elif key == "cw_gap":
                if self.current:
                    char = MORSE_TO_CHAR.get(self.current, "?")
                    self.text += char
                    self.current = ""
                if val == "word":
                    self.text += " "
                self.message_port_pub(pmt.intern("out"), pmt.intern(self.text))

        return len(in0)
