#!/usr/bin/env python3
"""
CODESYS XML Export Parser

This script parses exported CODESYS XML files (.export or .xml) to extract
useful information for documentation.

Usage:
    python3 parse-codesys-xml.py <export_file.export>
    python3 parse-codesys-xml.py <export_file.xml>
"""

import sys
import xml.etree.ElementTree as ET
from pathlib import Path
from typing import Dict, List, Optional


def parse_codesys_export(file_path: str) -> Dict:
    """Parse a CODESYS XML export file."""
    try:
        tree = ET.parse(file_path)
        root = tree.getroot()
        return extract_project_info(root)
    except ET.ParseError as e:
        print(f"Error parsing XML: {e}")
        return {}
    except Exception as e:
        print(f"Error reading file: {e}")
        return {}


def extract_project_info(root: ET.Element) -> Dict:
    """Extract project information from XML root."""
    info = {
        'project_name': '',
        'network_variables': [],
        'programs': [],
        'function_blocks': [],
        'io_config': [],
        'variables': []
    }
    
    # Try to find project name
    project_elem = root.find('.//Project')
    if project is not None:
        info['project_name'] = project_elem.get('Name', 'Unknown')
    
    # Extract network variables
    # (Structure depends on CODESYS version and export format)
    for nv in root.findall('.//NetworkVariable'):
        nv_info = {
            'name': nv.get('Name', ''),
            'type': nv.get('Type', ''),
            'direction': nv.get('Direction', ''),
            'initial_value': nv.get('InitialValue', '')
        }
        info['network_variables'].append(nv_info)
    
    # Extract programs/POUs
    for pou in root.findall('.//POU'):
        pou_info = {
            'name': pou.get('Name', ''),
            'type': pou.get('POUType', ''),
            'language': pou.get('Language', '')
        }
        info['programs'].append(pou_info)
    
    # Extract function blocks
    for fb in root.findall('.//FunctionBlock'):
        fb_info = {
            'name': fb.get('Name', ''),
            'type': fb.get('Type', '')
        }
        info['function_blocks'].append(fb_info)
    
    return info


def print_summary(info: Dict):
    """Print a summary of extracted information."""
    print("=" * 60)
    print("CODESYS Project Summary")
    print("=" * 60)
    
    if info.get('project_name'):
        print(f"\nProject Name: {info['project_name']}")
    
    if info.get('network_variables'):
        print(f"\nNetwork Variables ({len(info['network_variables'])}):")
        for nv in info['network_variables']:
            print(f"  - {nv['name']} ({nv['type']}) [{nv.get('direction', 'N/A')}]")
    
    if info.get('programs'):
        print(f"\nPrograms/POUs ({len(info['programs'])}):")
        for prog in info['programs']:
            print(f"  - {prog['name']} ({prog['type']}) [{prog.get('language', 'N/A')}]")
    
    if info.get('function_blocks'):
        print(f"\nFunction Blocks ({len(info['function_blocks'])}):")
        for fb in info['function_blocks']:
            print(f"  - {fb['name']} ({fb.get('type', 'N/A')})")
    
    print("\n" + "=" * 60)


def main():
    if len(sys.argv) < 2:
        print("Usage: python3 parse-codesys-xml.py <export_file.export|.xml>")
        sys.exit(1)
    
    file_path = sys.argv[1]
    
    if not Path(file_path).exists():
        print(f"Error: File not found: {file_path}")
        sys.exit(1)
    
    print(f"Parsing: {file_path}")
    info = parse_codesys_export(file_path)
    
    if info:
        print_summary(info)
        
        # Optionally save to JSON
        if len(sys.argv) > 2 and sys.argv[2] == '--json':
            import json
            output_file = Path(file_path).stem + '_parsed.json'
            with open(output_file, 'w') as f:
                json.dump(info, f, indent=2)
            print(f"\nParsed data saved to: {output_file}")
    else:
        print("No information extracted. The XML structure may be different.")
        print("Try opening the file in a text editor to inspect its structure.")


if __name__ == '__main__':
    main()
