#!/usr/bin/env python
# *************************************************************
#
#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you under the Apache License, Version 2.0 (the
#  "License"); you may not use this file except in compliance
#  with the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing,
#  software distributed under the License is distributed on an
#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#  KIND, either express or implied.  See the License for the
#  specific language governing permissions and limitations
#  under the License.
#
# *************************************************************


import getopt
import os
import re
import sys
#
from srclexer import SrcLexer
from srcparser import SrcParser
from boxer import Boxer
# FIXME
from globals import *

def option_parser ():
    import optparse
    p = optparse.OptionParser ()

    p.usage = '''src2xml.py [OPTION]... SRC-FILE...'''

    examples = '''
Examples:
  src2xml.py --output-dir=. --post-process --ignore-includes zoom.src
  src2xml.py --dry-run -I svx/inc -I svx/source/dialog zoom.src
'''

    def format_examples (self):
        return examples

    if 'epilog' in  p.__dict__:
        p.formatter.format_epilog = format_examples
        p.epilog = examples
    else:
        p.formatter.format_description = format_examples
        p.description = examples

    p.description = '''OOo SRC To Layout XML Converter.

Convert OO.o's existing dialog resource files into XML layout files.
'''

    p.add_option ('-l', '--debug-lexer', action='store_true',
                  dest='debug_lexer', default=False,
                  help='debug lexer')

    p.add_option ('-p', '--debug-parser', action='store_true',
                  dest='debug_parser', default=False,
                  help='debug parser')

    p.add_option ('-m', '--debug-macro', action='store_true',
                  dest='debug_macro', default=False,
                  help='debug macro')

    p.add_option ('-n', '--dry-run', action='store_true',
                  dest='dry_run', default=False,
                  help='dry run')

    p.add_option ('-k', '--keep-going', action='store_true',
                  dest='keep_going', default=False,
                  help='continue after error')

    p.add_option ('-i', '--ignore-includes', action='store_true',
                  dest='ignore_includes', default=False,
                  help='ignore #include directives')

    p.add_option ('-I', '--include-dir', action='append',
                  dest='include_path',
                  default=[],
                  metavar='DIR',
                  help='append DIR to include path')

    def from_file (option, opt_str, value, parser):
        lst = getattr (parser.values, option.dest)
        lst += file (value).read ().split ('\n')
        setattr (parser.values, option.dest, lst)

    def from_path (option, opt_str, value, parser):
        lst = getattr (parser.values, option.dest)
        lst += value.split (':')
        setattr (parser.values, option.dest, lst)

    # Junk me?
    p.add_option ('--includes-from-file', action='callback', callback=from_file,
                  dest='include_path',
                  default=[],
                  type='string',
                  metavar='FILE',
                  help='append directory list from FILE to include path')

    p.add_option ('--include-path', action='callback', callback=from_path,
                  dest='include_path',
                  type='string',
                  default=[],
                  metavar='PATH',
                  help='append PATH to include path')

    p.add_option ('--only-expand-macros', action='store_true',
                  dest='only_expand_macros', default=False,
                  help='FIXME: better to say what NOT to expand?')

    p.add_option ('-o', '--output-dir', action='store',
                  dest='output_dir', default=None,
                  metavar='DIR',
                  help='Output to DIR')

    p.add_option ('-s', '--post-process', action='store_true',
                  dest='post_process', default=False,
                  help='post process output for use in Layout')

    p.add_option ('--stop-on-header', action='store_true',
                  dest='stopOnHeader', default=False,
                  help='FIXME: remove this?')

    return p


def convert (file_name, options):
    progress ("parsing %(file_name)s ..." % locals ())
    fullpath = os.path.abspath(file_name)
    if not os.path.isfile(fullpath):
        error("no such file", exit=True)

    ##options.include_path.append (os.path.dirname (fullpath))

    input = file (fullpath, 'r').read()
    lexer = SrcLexer(input, fullpath)
    lexer.expandHeaders = not options.ignore_includes
    lexer.includeDirs = options.include_path
    lexer.stopOnHeader = options.stopOnHeader
    lexer.debugMacro = options.debug_macro
    if options.debug_lexer:
        lexer.debug = True
        lexer.tokenize()
        progress ("-"*68 + "\n")
        progress ("** token dump\n")
        lexer.dumpTokens()
        progress ("** end of token dump\n")
        return

    # Tokenize it using lexer
    lexer.tokenize()

    parser = SrcParser(lexer.getTokens(), lexer.getDefines())
    parser.only_expand_macros = options.only_expand_macros
    if options.debug_parser:
        parser.debug = True
        root = parser.parse()
        s = root.dump()
        return s

    # Parse the tokens.
    root = parser.parse()

    # Box it, and return the XML tree.
    root = Boxer(root).layout()
    output = root.dump()
    if not options.dry_run:
        progress ("\n")
    return output

def dry_one_file (file_name, options):
    try:
        str = convert(file_name, options)
        progress ("  SUCCESS\n")
    except Exception as e:
        if options.keep_going:
            progress ("  FAILED\n")
        else:
            import traceback
            print(traceback.format_exc (None))
            raise e

def post_process (s):
    """Make output directly usable by layout module."""
    s = re.sub ('(</?)([a-z]+)-([a-z]+)-([a-z]+)', r'\1\2\3\4', s)
    s = re.sub ('(</?)([a-z]+)-([a-z]+)', r'\1\2\3', s)
    s = re.sub ('(<(checkbox|(cancel|help|ignore|ok|push|more|no|radio|reset|retry|yes)button|(fixed(info|text)))[^>]*) text=', r'\1 label=', s)
    s = re.sub (' (height|width|x|y)="[0-9]*"', '', s)
    s = re.sub (' (label|text|title)="', r' _\1="', s)
    s = re.sub ('&([^m][^p]*[^;]*)', r'&amp;\1', s)
    s = re.sub (' hide="(TRUE|true|1)"', ' show="false"', s)

    s = s.replace ('<modaldialog', '<modaldialog sizeable="true"')
    s = s.replace (' rid=', ' id=')
    s = s.replace (' border="true"', ' has_border="true"')
    s = s.replace (' def-button="true"', ' defbutton="true"')
    s = s.replace (' drop-down="', ' dropdown="')
    s = s.replace (' tab-stop="', ' tabstop="')
    return s

XML_HEADER = '''<?xml version="1.0" encoding="UTF-8"?>
<!-- This is a template.  i18n translation is not performed in-place;
     i18n translated XML files are generated from this template by
     transex3/layout/tralay.  !-->
'''

def do_one_file (file_name, options):
    str = XML_HEADER
    str += convert(file_name, options)
    str += '\n'

    if options.post_process:
        str = post_process (str)
    h = sys.stdout
    if options.output_dir:
        base = os.path.basename (file_name)
        root, ext = os.path.splitext (base)
        out_name = options.output_dir + '/' + root + '.xml'
        progress ("writing %(out_name)s ..." % locals ())
        h = file (out_name, 'w')
    h.write (str)
    h.flush ()
    progress ("\n")

def main ():
    p = option_parser ()
    (options, files) = option_parser ().parse_args ()
    if not files:
        p.error ("no input files")

    for f in files:
        if options.dry_run:
            dry_one_file (f, options)
        else:
            do_one_file (f, options)

if __name__ == '__main__':
    main ()
