#!/usr/bin/env python

import sys, os, getopt
from dircache import listdir

######################################################################
## You may want to change these variables

## The name of the output file when using the -r/--result-file option
RES_FILENAME = "check-translation.res"

## The first part of the pak-filename (ex. building.XXX.pak)
PAK_FILENAME_PREFIXES = ["bridge", "building", "factory", "good", "vehicle"]

## Some pak-filenames that we don't have to translate.
##  the names are the middle part of the pak-filename (ex. xxx.BusStop.pak)
PAK_FILENAME_EXCLUDES = ["BusStop", "CarDepot", "CarStop", "ShipDepot",
                    "ShipStop", "TrainDepot", "TrainStop", "PostOffice",
                    "02_CITY", "03_CITY", "03_CITY_A", "03_CITY_B",
                    "03_CITY_C", "04_CITY", "04_CITY_B","04_CITY_C",
                    "None"]

######################################################################

PREFIXES_FORMATTED = ", ".join (PAK_FILENAME_PREFIXES)
EXCLUDES_FORMATTED = ", ".join (PAK_FILENAME_EXCLUDES)

PY_COMMAND = "python check-translation.py"

SHORT_USAGE = "\n".join([
    "usage: %(PY_COMMAND)s [option [parameter]] <translationfile>",
    " The script checks <translationfile> (a Simutrans .tab file)" +\
    " according to the used options."])\
    % (globals ())

NO_OPTIONS = "\n".join([
    "Used without options (or with the -r option only):",
    "- The translation file is checked for uneven line count.",
    "- A list containing the original (untranslated) words with linenumbers is printed.",
    "- A list containing the translations with linenumbers is printed.",
    "- The comment lines are printed."])

HELP_OPTION = "\n".join([
    "-h/--help :",
    " prints this message and exits.",
    " Example: '%(PY_COMMAND)s -h'"])\
    % (globals ())

RESULTFILE_OPTION = "\n".join([
    "-r/--result-file :",
    " appends output to file named 'check-translation.res'",
    " Example: '%(PY_COMMAND)s --result-file myLang.tab'"])\
    % (globals ())

COMPAREFILE_OPTION = "\n".join([
    "-c <file>/--compare-file=<file> :",
    " Compares translationfile with compare-file",
    "  i.e. writes all original words found ONLY in compare-file.",
    " Example: '%(PY_COMMAND)s -c simutrans/de.tab /home/me/myLang.tab'"])\
    % (globals ())

PAKDIRECTORY_OPTION = "\n".join([
    "-p <pak-dir>/--pak-directory=<pak-dir> :",
    " Compares translationfile with nameparts from pak-filenames found in <pak-dir>",
    "  i.e. writes all nameparts found ONLY in pak-filenames.",
    " The pak-filenames have the format: prefix.namepart.pak",
    " The used pak-filenames are all names having the prefixes",
    " - %(PREFIXES_FORMATTED)s",
    " excluding those having the nameparts",
    " - %(EXCLUDES_FORMATTED)s",
    " Example: '%(PY_COMMAND)s --pak-directory=simutrans/pak myLang.tab'",
    " NOTE !!  Don't use any space between a long option, the '=' and the parameter"])\
    % (globals ())

OPTIONS_PART = "\n\n".join(["Possible options are:",
                          HELP_OPTION,
                          RESULTFILE_OPTION,
                          COMPAREFILE_OPTION,
                          PAKDIRECTORY_OPTION])

ORIG_HEADER = "\nORIGINAL WORDS:\n"
TRANS_HEADER = "\nTRANSLATED WORDS:\n"
COMM_HEADER = "\nCOMMENTS:\n"
CMP_HEADER = "\nOriginal words found ONLY in %s :\n"
PAK_HEADER = "\nNames found ONLY in pak-directory %s :\n"


def usage ():
    print "%(SHORT_USAGE)s\n\n%(NO_OPTIONS)s\n\n%(OPTIONS_PART)s"\
          % (globals())

def short_usage ():
    print "\n%(SHORT_USAGE)s\n (try '-h/--help' option for full usage)"\
          % (globals())
        
def print_error (error):
    print
    print "ERROR in command:", " ".join(sys.argv)
    print "ERROR:", error

def get_lines (filename):
    result = []
    try:
        fil = file(filename)
        result = fil.readlines()
        fil.close ()
    except IOError, error:
        print_error(error)
    return result

def check_linecount (filename, filetype, linecount):
    print
    if (linecount % 2):
        print "\n".join(["Checking %(filetype)s : %(filename)s",
              " for uneven linecount : OK"])  % (locals ())
    else:
        print "\n".join(["ERROR: %(filetype)s : %(filename)s",
                         " contains even number (%(linecount)d) of lines"])\
                         % (locals ()) 

def divide_lines (lines):
    lines_count = len (lines)
    originals, translations, comments = [],[],[]
    for lineno in range (1, lines_count):
        line = lines[lineno]
        if line.strip().startswith ('#'):
            comments.append (format_line(lineno, line))
        elif (lineno % 2):
            originals.append (format_line(lineno, line))
        else:
            translations.append (format_line(lineno, line))
    return (originals, translations, comments)

def format_line (lineno, line):
    return "".join([str(lineno), ":", line])

def get_word (formatted_line):
    return formatted_line.split(':')[1][:-1]

def join_with_header (header, lines):
    return "".join([header, "".join(lines)])

def get_parameter (short_opt, long_opt, actual_opts):
    return ((short_opt in actual_opts) and actual_opts[short_opt])\
           or actual_opts[long_opt]

def get_pakdir_words (pakdir):
    pak_files = listdir(pakdir)
    result = [get_name_part(pak_filename) for pak_filename in pak_files
              if get_prefix_part(pak_filename) in PAK_FILENAME_PREFIXES
              and not get_name_part(pak_filename) in PAK_FILENAME_EXCLUDES]
    return result

def get_name_part (pak_filename):
    return pak_filename.split(".")[1]
    
def get_prefix_part (pak_filename):
    return pak_filename.split(".")[0].split()[-1]

def output(lines, result_file = False):
    streams = (result_file and [sys.stdout, file(RES_FILENAME, 'a+')])\
              or [sys.stdout]
    lines.append ("\n")
    for stream in streams:
        map(stream.write, lines)
    if result_file: streams[1].close()

def main ():
    shortopts = "c:p:rh"
    longopts = ["compare-file=", "pak-directory=", "result-file", "help"]
    try:
        opts, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
    except getopt.GetoptError, error:
        print_error(error)
        sys.exit(1)

    actual_opts = dict(opts)

    if ("-h" in actual_opts) or ("--help" in actual_opts):
        usage ()
        sys.exit(0)

    if not args:
        print_error ("No translationfile argument")
        short_usage ()
        sys.exit(1)

    translation_file = args[0]
    tf_lines = get_lines (translation_file)

    check_linecount (translation_file, "translation file", len(tf_lines))

    result_file = ("-r" in actual_opts) or ("--resultfile" in actual_opts)

    tf_originals, tf_translations, tf_comments = divide_lines (tf_lines)

    ##  no options or only -r option
    if (not actual_opts) or (len(actual_opts) == 1 and result_file):
        output([join_with_header(ORIG_HEADER, tf_originals),
                join_with_header(TRANS_HEADER, tf_translations),
                join_with_header(COMM_HEADER, tf_comments)],
               result_file)

    if ("-c" in actual_opts) or ("--compare-file" in actual_opts):
        compare_file = get_parameter("-c", "--compare-file", actual_opts)
        cmp_lines = get_lines (compare_file)
        check_linecount (compare_file, "compare file", len(cmp_lines))
        cmp_originals = divide_lines (cmp_lines)[0]

        orig = [get_word(line) for line in tf_originals]
        missing_words = [line for line in cmp_originals
                         if get_word(line) not in orig]
        header = CMP_HEADER % compare_file
        output ([join_with_header(header, missing_words)], result_file)

    if ("-p" in actual_opts) or ("pak-directory" in actual_opts):
        pakdir = get_parameter("-p", "--pak-directory", actual_opts)
        pakdir_words = get_pakdir_words (pakdir)

        orig = [get_word(line) for line in tf_originals]
        missing_words = [word for word in pakdir_words if word not in orig]
        header = PAK_HEADER % pakdir
        output ([join_with_header(header, "\n".join(missing_words))],
                result_file)

if __name__ == "__main__":
    main ()
