import re
import math
def parse_lyrics(lyrics, theme_name):
    """
    Parses Planning Center Lyrics and returns an list of verses, where each 
    verse is a dictionary that looks like:
        verse['verse_type']
        verse['verse_number']
        verse['verse_text']
    :param lyrics: Lyrics String from Planning Center
    :theme_name: Video or standard - to decide how many lines each slide should have
    """
    # create a regular expression for potential VERSE,CHORUS tags included inline inside the lyrics...
    verse_marker_pattern = re.compile('^(verse?|v|chorus|c|refreng|bridge|bro|prechorus|instrumental|intro|outro|vamp|breakdown|ending|interlude|tag|misc)\s*(\d*):?$',re.IGNORECASE)
    # create regex for an END marker.  content after this marker will be ignored
    end_marker_pattern = re.compile('^{(<.*?>)?END(<.*?>)?}$')

    type_count = {}
    verse_number = ''
    verse_lines = []
    is_end_marker = False
    output_verses = []
    input_verses = lyrics.split("\n\n")
    for verse in input_verses:
        verse_type = ''
        for line in verse.split("\n"):
            if end_marker_pattern.search(line):
                # see if this is the end marker (stop parsing verses if it is)
                is_end_marker = True
                
            # strip out curly braces and the content inside {}
            line = re.sub('{.*?}+','',line)
            # strip out any extraneous tags <...>
            line = re.sub('<.*?>','',line)
            # remove beginning/trailing whitespace and line breaks
            line = line.rstrip()
            line = line.lstrip()
            
            regex_match = verse_marker_pattern.search(line)
            if regex_match:
                if len(verse_lines) and verse_type != '':
                    # if we have verse_lines from the previous verse, submit it now
                    add_verse(output_verses, verse_type, verse_number, verse_lines, type_count, theme_name)
                    verse_lines = []
                verse_type = lookup_openlp_verse_type(regex_match.group(1))
                # if we have a number after the verse marker, capture it here
                if regex_match.group(2):
                    verse_number = regex_match.group(2)
                else:
                    # if empty, let openlp auto-create it for us
                    verse_number = ''
                continue
            else:
                verse_lines.append(line)

        if len(verse_lines):
            if verse_type != '':                
                add_verse(output_verses, verse_type, verse_number, verse_lines, type_count, theme_name)
            
            verse_lines = []
            if is_end_marker:
                return output_verses
    return output_verses


# def parse_sequence(sequence):
#     """
#     Orders a list of verses by a specified Planning Center sequence
#     :param sequence: The sequence array.
#     """
#     return ' '.join([verse_key(lookup_openlp_verse_type(element['label']), element['number']) for element in sequence])
        

def lookup_openlp_verse_type(pco_verse_type):
    """
    Provides a lookup table to map from a Planning Center Verse Type
    to an OpenLP verse type.
    :param pco_verse_type: Planning Center Verse Type String
    """
    pco_verse_type_to_openlp = {}
    pco_verse_type_to_openlp['VERSE'] = 'v'
    pco_verse_type_to_openlp['VERS'] = 'v'
    pco_verse_type_to_openlp['V'] = 'v'
    pco_verse_type_to_openlp['C'] = 'c'
    pco_verse_type_to_openlp['CHORUS'] = 'c'
    pco_verse_type_to_openlp['REFRENG'] = 'c'
    pco_verse_type_to_openlp['PRECHORUS'] = 'p'
    pco_verse_type_to_openlp['INTRO'] = 'i'
    pco_verse_type_to_openlp['ENDING'] = 'e'
    pco_verse_type_to_openlp['BRIDGE'] = 'b'
    pco_verse_type_to_openlp['BRO'] = 'b'
    pco_verse_type_to_openlp['OTHER'] = 'o'
    
    openlp_verse_type = pco_verse_type_to_openlp['OTHER']
    if pco_verse_type.upper() in pco_verse_type_to_openlp:
        openlp_verse_type = pco_verse_type_to_openlp[pco_verse_type.upper()]
    
    return openlp_verse_type

def add_verse(output_verses, verse_type, verse_number, verse_lines, type_count, theme_name):
    """
    Simple utility function that takes verse attributes and adds the verse
    to the output_verses list.
    :param output_verses: The list of verses that will ultimately be returned by 
    the _SplitLyricsIntoVerses function
    :param output_verses: The list to add this verse to
    :param verse_type: The OpenLP Verse Type, like v,c,e, etc...
    :param verse_number: The verse number, if known, like 1, 2, 3, etc.
    :param verse_lines: The parsed verse text returned from _SplitLyricsIntoVerses
    :param type_count: A dictionary holding the count of past types
    :param theme_name: Video or standard. Defines how many lines a slide should have
    """
    type_count[verse_type] = 1 if verse_type not in type_count else type_count[verse_type] + 1
    verse_number = verse_number if verse_number != '' else type_count[verse_type] if verse_type in type_count else '1'

    count = len(verse_lines)
    verse = []

    ##calculate slide layout
    lines=count
    num=math.ceil(lines/6)
    linesSlide1=0
    slide1Full=False
    linesSlide2=0
    slide2Full=False
    fullSlides=0

    if lines<7:
        linesSlide1=lines

    elif (num<3 and lines<13):
        linesSlide1 = math.ceil(lines/2)
        linesSlide2 = lines-math.ceil(lines/2)

    elif (lines >= 13):
        linesLeft = lines-(6*(num-2))
        linesSlide1 = math.ceil(linesLeft/2)
        linesSlide2 = linesLeft-math.ceil(linesLeft/2)
        fullSlides = num-2
    
    if(lines>13):
        print(f"lines={lines} slide1={linesSlide1} - slide2={linesSlide2} - fullSlides={fullSlides} - lines={lines} and num={math.ceil(num)}")

    ##calculate slide layout - END

    counter=1    
    for i in range(count):
        
        verse.append(verse_lines[i])
        if theme_name == 'video':
            if ((i+1) % 2 == 0):
                output_verses.append(create_verse_object(verse_type, verse_number, "\n".join(verse)))
                verse = []
        elif (fullSlides>0):
            if ((i+1) % 6 == 0):
                output_verses.append(create_verse_object(verse_type, verse_number, "\n".join(verse)))
                verse = []
                counter=0
                fullSlides=fullSlides-1
        elif (not slide1Full):
             #if ((i+1) == linesSlide1):
             if (counter == linesSlide1):
                output_verses.append(create_verse_object(verse_type, verse_number, "\n".join(verse)))
                verse = []
                counter=0
                slide1Full=True
        elif (not slide2Full):
              #if ((i+1) == linesSlide2):
              if ((counter) == linesSlide2):
                output_verses.append(create_verse_object(verse_type, verse_number, "\n".join(verse)))
                verse = []
                counter=0
                slide2Full=True

        counter=counter+1

    if (len(verse)):
        output_verses.append(create_verse_object(verse_type, verse_number, "\n".join(verse)))
    
    return output_verses

def verse_key(verse_type, verse_number):
    return str(verse_type) + str(verse_number)

def create_verse_object(verse_type, verse_number, verse_text):
    return {
        'verse_type': verse_type,
        'verse_number': str(verse_number),
        'verse_text': verse_text
    }
