#!/usr/bin/python
# 
# Copyright 2002, 2003 Zuza Software Foundation
# 
# This file is part of translate.
#
# translate is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# translate is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with translate; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

"""simple script to run all check filters on gettext .po localization file(s)"""

from translate.storage import po
from translate.filters import checks

class pocheckfilter:
  def __init__(self, checker=None):
    """builds a pocheckfilter using the given checker"""
    if checker is None:
      self.checker = checks.StandardChecker()
    else:
      self.checker = checker

  def getfilterdocs(self):
    """lists the docs for filters available on checker..."""
    filterdict = self.checker.getfilters()
    filterdocs = ["%s\t%s" % (name, filterfunc.__doc__) for (name, filterfunc) in filterdict.iteritems()]
    filterdocs.sort()
    return "\n".join(filterdocs)

  def filterelement(self, thepo, includereview=1, includefuzzy=0, excludefilters={}, limitfilters=None):
    """runs filters on an element"""
    if thepo.isheader(): return []
    if thepo.hasplural():
      unquotedid = po.getunquotedstr(thepo.msgid)
      unquotedstr = po.getunquotedstr(thepo.msgstr[0])
      failures = self.checker.run_filters(unquotedid, unquotedstr, excludefilters, limitfilters)
      unquotedid = po.getunquotedstr(thepo.msgid_plural)
      unquotedstr = po.getunquotedstr(thepo.msgstr[1])
      failures += self.checker.run_filters(unquotedid, unquotedstr, excludefilters, limitfilters)
    else:
      unquotedid = po.getunquotedstr(thepo.msgid)
      unquotedstr = po.getunquotedstr(thepo.msgstr)
      failures = self.checker.run_filters(unquotedid, unquotedstr, excludefilters, limitfilters)
    if not failures:
      if includereview and thepo.hastypecomment("review"):
        failures.append("marked for review")
      if includefuzzy and thepo.isfuzzy():
        failures.append("fuzzy")
    return failures

  def filterfile(self, thepofile, includereview=1, includefuzzy=0, excludefilters={}, limitfilters=None):
    """runs filters on a file"""
    thenewpofile = po.pofile()
    for thepo in thepofile.poelements:
      failures = self.filterelement(thepo, includereview, includefuzzy, excludefilters, limitfilters)
      if failures:
        thepo.visiblecomments.extend(["#_ %s\n" % failure for failure in failures])
        if ("".join(thepo.typecomments)).find("fuzzy") == -1:
          thepo.typecomments.append("#, fuzzy\n")
        thenewpofile.poelements.append(thepo)
    return thenewpofile

# TODO: refactor to set the filter list once, and use every time, rather than recreating for each file
def runpofilter(inputfile, outputfile, includereview=False, includefuzzy=False, filterobject=None, excludefilters={}, limitfilters=None, listfilters=False):
  """reads in inputfile using po.pofile, filters using pocheckfilter, writes to stdout"""
  checkfilter = pocheckfilter(filterobject)
  if listfilters:
    print checkfilter.getfilterdocs()
    return
  fromfile = po.pofile(inputfile)
  tofile = checkfilter.filterfile(fromfile, includereview, includefuzzy, excludefilters, limitfilters)
  if tofile.isempty():
    return 0
  tolines = tofile.tolines()
  outputfile.writelines(tolines)
  return 1

if __name__ == '__main__':
  from translate.filters import filtercmd
  inputformats = {"po":runpofilter, "pot":runpofilter}
  parser = filtercmd.FilterOptionParser(filtercmd.optionalrecursion, inputformats)
  parser.add_option("", "--review", dest="includereview",
    action="store_true", default=False,
    help="include elements marked for review")
  parser.add_option("", "--ignorereview", dest="includereview",
    action="store_false", default=False,
    help="don't include elements marked for review")
  parser.add_option("", "--fuzzy", dest="includefuzzy",
    action="store_true", default=False,
    help="include elements marked fuzzy")
  parser.add_option("", "--openoffice", dest="filterobject",
    action="store_const", default=None, const=checks.OpenOfficeChecker(),
    help="use the standard checks for OpenOffice translations")
  parser.add_option("", "--mozilla", dest="filterobject",
    action="store_const", default=None, const=checks.MozillaChecker(),
    help="use the standard checks for Mozilla translations")
  parser.add_option("", "--gnome", dest="filterobject",
    action="store_const", default=None, const=checks.GnomeChecker(),
    help="use the standard checks for Gnome translations")
  parser.add_option("", "--kde", dest="filterobject",
    action="store_const", default=None, const=checks.KdeChecker(),
    help="use the standard checks for KDE translations")
  parser.add_option("-x", "--exclude", dest="excludefilters",
    action="append", default=[], type="string", metavar="FILTER",
    help="don't use FILTER when filtering")
  parser.add_option("-t", "--test", dest="limitfilters",
    action="append", default=None, type="string", metavar="FILTER",
    help="only use test FILTERs specified with this option when filtering")
  parser.add_option("-l", "--listfilters", dest="listfilters",
    action="store_true", default=False, help="list filters available")
  requiredoptions = dict([(key, True) for key in 
    ('includereview', 'includefuzzy', 'filterobject', 'excludefilters', 'limitfilters', 'listfilters')])
  options, args = parser.parse_args()
  # TODO: move this code into filtercmd...
  if options.input is None:
    if len(args) == 0:
      parser.runfilter(options, runpofilter, requiredoptions)
    else:
      for inputarg in args:
        options.input = inputarg
        parser.runfilter(options, runpofilter, requiredoptions)
  else:
    if len(args) != 0:
      parser.error("incorrect number of arguments")
    parser.runfilter(options, runpofilter, requiredoptions)

