import xml.etree.ElementTree as ET
import os
import uuid

def timecode_to_frames(timecode, fps=30):
    # Assuming timecode format is hh:mm:ss
    parts = timecode.split(":")
    hours = int(parts[0])
    minutes = int(parts[1])
    seconds = float(parts[2])
    total_seconds = hours * 3600 + minutes * 60 + seconds
    return int(total_seconds * fps)

def parse_custom_xml(file_path):
    # Read and fix the XML content
    with open(file_path, 'r', encoding='utf-8') as f:
        content = f.read()

    # Fix the XML structure by wrapping <Chapter> elements inside <ChapterMarkers>
    if '</ChapterMarkers>' in content:
        index = content.index('</ChapterMarkers>') + len('</ChapterMarkers>')
        chapters_content = content[index:].strip()
        content = content[:index]
        # Insert the chapters inside the <ChapterMarkers> element
        content = content.replace('</ChapterMarkers>', chapters_content + '\n</ChapterMarkers>')

    # Parse the corrected XML
    root = ET.fromstring(content)
    title_elem = root.find('Title')
    title = title_elem.text if title_elem is not None else 'Untitled'

    chapters = []
    for chapter_elem in root.findall('Chapter'):
        name_elem = chapter_elem.find('Name')
        timestamp_elem = chapter_elem.find('Timestamp')
        source_elem = chapter_elem.find('Source')
        chapter = {
            'Name': name_elem.text if name_elem is not None else '',
            'Timestamp': timestamp_elem.text if timestamp_elem is not None else '00:00:00',
            'Source': source_elem.text if source_elem is not None else '',
        }
        chapters.append(chapter)

    return title, chapters

def create_fcpxml(chapters, sequence_name, fps=30):
    fcpxml = ET.Element('xmeml', version="4")
    fcpxml.tail = '\n'

    # Adding DOCTYPE manually because ElementTree doesn't support it
    doctype = '<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE xmeml>'

    sequence = ET.SubElement(fcpxml, 'sequence', {'id': 'sequence-1'})
    sequence.tail = '\n\t'

    # Add necessary elements to sequence
    uuid_elem = ET.SubElement(sequence, 'uuid')
    uuid_elem.text = str(uuid.uuid4())

    duration_frames = max([timecode_to_frames(ch['Timestamp'], fps) for ch in chapters]) + fps
    duration_elem = ET.SubElement(sequence, 'duration')
    duration_elem.text = str(duration_frames)

    rate_elem = ET.SubElement(sequence, 'rate')
    timebase_elem = ET.SubElement(rate_elem, 'timebase')
    timebase_elem.text = str(fps)
    ntsc_elem = ET.SubElement(rate_elem, 'ntsc')
    ntsc_elem.text = 'FALSE'

    name_elem = ET.SubElement(sequence, 'name')
    name_elem.text = sequence_name  # Use the sequence name derived from input filename

    # Add empty media elements (required by Premiere Pro)
    media_elem = ET.SubElement(sequence, 'media')
    video_elem = ET.SubElement(media_elem, 'video')
    audio_elem = ET.SubElement(media_elem, 'audio')

    # Add timecode (required by Premiere Pro)
    timecode_elem = ET.SubElement(sequence, 'timecode')
    rate_tc_elem = ET.SubElement(timecode_elem, 'rate')
    timebase_tc_elem = ET.SubElement(rate_tc_elem, 'timebase')
    timebase_tc_elem.text = str(fps)
    ntsc_tc_elem = ET.SubElement(rate_tc_elem, 'ntsc')
    ntsc_tc_elem.text = 'FALSE'
    string_tc_elem = ET.SubElement(timecode_elem, 'string')
    string_tc_elem.text = '00:00:00:00'
    frame_tc_elem = ET.SubElement(timecode_elem, 'frame')
    frame_tc_elem.text = '0'
    displayformat_tc_elem = ET.SubElement(timecode_elem, 'displayformat')
    displayformat_tc_elem.text = 'NDF'

    # Add markers
    for ch in chapters:
        marker_elem = ET.SubElement(sequence, 'marker')
        marker_name_elem = ET.SubElement(marker_elem, 'name')
        marker_name_elem.text = ch['Name']

        marker_comment_elem = ET.SubElement(marker_elem, 'comment')
        marker_comment_elem.text = ch['Source']

        marker_in_elem = ET.SubElement(marker_elem, 'in')
        marker_in_elem.text = str(timecode_to_frames(ch['Timestamp'], fps))

        marker_out_elem = ET.SubElement(marker_elem, 'out')
        marker_out_elem.text = '-1'

    return fcpxml, doctype

def save_fcpxml(fcpxml, output_file, doctype):
    # Write the XML to a file with the DOCTYPE
    xml_str = ET.tostring(fcpxml, encoding='UTF-8')
    xml_pretty = minidom.parseString(xml_str).toprettyxml(indent="    ")

    with open(output_file, 'w', encoding='utf-8') as f:
        f.write(doctype)
        f.write('\n')
        # Remove the XML declaration added by toprettyxml()
        xml_content = '\n'.join(xml_pretty.split('\n')[1:])
        f.write(xml_content)

if __name__ == '__main__':
    import sys
    import xml.dom.minidom as minidom

    # Ask for the input file path
    input_file = input("Please enter the full path of the input XML file: ").strip('\"')

    try:
        title, chapters = parse_custom_xml(input_file)

        # Extract input filename without extension to use as sequence name
        input_filename = os.path.basename(input_file)
        input_name, input_ext = os.path.splitext(input_filename)
        sequence_name = input_name  # Set sequence name to input file name without extension

        fcpxml, doctype = create_fcpxml(chapters, sequence_name)

        # Save output file in the same folder as the input file with '_CONVERTED' appended
        input_dir = os.path.dirname(input_file)
        output_filename_base = input_name + '_CONVERTED'
        output_ext = input_ext
        output_filename = output_filename_base + output_ext
        output_file = os.path.join(input_dir, output_filename)

        # If output file exists, append a number to the filename
        counter = 1
        while os.path.exists(output_file):
            output_filename = f"{output_filename_base}_{counter}{output_ext}"
            output_file = os.path.join(input_dir, output_filename)
            counter += 1

        save_fcpxml(fcpxml, output_file, doctype)

        print(f"Final Cut Pro XML saved to {output_file}")
    except Exception as e:
        print(f"An error occurred: {e}")
