#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 
# Copyright 2004-2006 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

"""Converts gettext .pot template to .po translation files, merging in existing translations if present."""

from translate.storage import po
from translate.storage import factory
from translate.search import match

# We don't want to reinitialise the TM each time, so let's store it here.
tmmatcher = None

def memory(tmfiles, max_candidates=1, min_similarity=75, max_length=1000):
    """Returns the TM store to use. Only initialises on first call."""
    global tmmatcher
    # Only initialise first time
    if tmmatcher is None:
      if isinstance(tmfiles, list):
        tmstore = [factory.getobject(tmfile) for tmfile in tmfiles]
      else:
        tmstore = factory.getobject(tmfiles)
      tmmatcher = match.matcher(tmstore, max_candidates=max_candidates, min_similarity=min_similarity, max_length=max_length)
    return tmmatcher

def convertpot(inputpotfile, outputpofile, templatepofile, tm=None, min_similarity=75, fuzzymatching=True):
  """reads in inputpotfile, adjusts header, writes to outputpofile. if templatepofile exists, merge translations from it into outputpofile"""
  inputpot = po.pofile(inputpotfile)
  inputpot.makeindex()
  outputpo = po.pofile()
  # header values
  charset = "UTF-8"
  encoding = "8bit"
  project_id_version = None
  pot_creation_date = None
  po_revision_date = None
  last_translator = None
  language_team = None
  mime_version = None
  plural_forms = None
  kwargs = {}
  if templatepofile is not None:
    templatepo = po.pofile(templatepofile)
    fuzzyfilematcher = None
    if fuzzymatching:
        for unit in templatepo.units:
          if unit.isobsolete():
            unit.resurrect()
        try:
          fuzzyfilematcher = match.matcher(templatepo, max_candidates=1, min_similarity=min_similarity, max_length=1000)
          fuzzyfilematcher.addpercentage = False
        except ValueError:
          pass

    templatepo.makeindex()
    templateheadervalues = templatepo.parseheader()
    for key, value in templateheadervalues.iteritems():
      if key == "Project-Id-Version":
        project_id_version = value
      elif key == "Last-Translator":
        last_translator = value
      elif key == "Language-Team":
        language_team = value
      elif key == "PO-Revision-Date":
        po_revision_date = value
      elif key in ("POT-Creation-Date", "MIME-Version"):
        # don't know how to handle these keys, or ignoring them
        pass
      elif key == "Content-Type":
        kwargs[key] = value
      elif key == "Content-Transfer-Encoding":
        encoding = value
      elif key == "Plural-Forms":
        plural_forms = value
      else:
        kwargs[key] = value
  fuzzyglobalmatcher = None
  if fuzzymatching:
    try:
      fuzzyglobalmatcher = memory(tm, max_candidates=1, min_similarity=min_similarity, max_length=1000)
      fuzzyglobalmatcher.addpercentage = False
    except ValueError:
      pass
  inputheadervalues = inputpot.parseheader()
  for key, value in inputheadervalues.iteritems():
    if key in ("Project-Id-Version", "Last-Translator", "Language-Team", "PO-Revision-Date", "Content-Type", "Content-Transfer-Encoding", "Plural-Forms"):
      # want to carry these from the template so we ignore them
      pass
    elif key == "POT-Creation-Date":
      pot_creation_date = value
    elif key == "MIME-Version":
      mime_version = value
    else:
      kwargs[key] = value
  outputheaderpo = outputpo.makeheader(charset=charset, encoding=encoding, project_id_version=project_id_version,
    pot_creation_date=pot_creation_date, po_revision_date=po_revision_date, last_translator=last_translator,
    language_team=language_team, mime_version=mime_version, plural_forms=plural_forms, **kwargs)
  # Get the header comments and fuzziness state
  if templatepofile is not None:
    if templatepo.units[0].isheader():    
      if templatepo.units[0].getnotes():
        outputheaderpo.addnote(templatepo.units[0].getnotes())
      outputheaderpo.markfuzzy(templatepo.units[0].isfuzzy())
  elif inputpot.units[0].isheader():
    outputheaderpo.addnote(inputpot.units[0].getnotes())
  outputpo.units.append(outputheaderpo)
  # Do matching
  for inputpotunit in inputpot.units:
    if not (inputpotunit.isheader() or inputpotunit.isobsolete()):
      if templatepofile:
        possiblematches = []
        for location in inputpotunit.getlocations():
          templatepounit = templatepo.locationindex.get(location, None)
          if templatepounit is not None:
            possiblematches.append(templatepounit)
        if len(inputpotunit.getlocations()) == 0:
          templatepounit = templatepo.findunit(inputpotunit.source)
        if templatepounit:
          possiblematches.append(templatepounit)
        for templatepounit in possiblematches:
          if inputpotunit.source == templatepounit.source and templatepounit.target:
            inputpotunit.merge(templatepounit, authoritative=True)
            break
        else:
          fuzzycandidates = []
          if fuzzyfilematcher:
            fuzzycandidates = fuzzyfilematcher.matches(inputpotunit.source)
            if fuzzycandidates:
              inputpotunit.merge(fuzzycandidates[0])
              original = templatepo.findunit(fuzzycandidates[0].source)
              if original:
                original.reused = True
          if fuzzyglobalmatcher and not fuzzycandidates:
            fuzzycandidates = fuzzyglobalmatcher.matches(inputpotunit.source)
            if fuzzycandidates:
              inputpotunit.merge(fuzzycandidates[0])
        outputpo.units.append(inputpotunit)
      else:
        if fuzzyglobalmatcher:
          fuzzycandidates = fuzzyglobalmatcher.matches(inputpotunit.source)
          if fuzzycandidates:
            inputpotunit.merge(fuzzycandidates[0])
        outputpo.units.append(inputpotunit)

  #Let's take care of obsoleted messages
  if templatepofile:
    newlyobsoleted = []
    for unit in templatepo.units:
      if unit.target and not (inputpot.findunit(unit.source) or hasattr(unit, "reused")):
        #not in .pot, make it obsolete
        unit.makeobsolete()
        newlyobsoleted.append(unit)
      elif unit.isobsolete():
        outputpo.units.append(unit)
    outputpo.units.extend(newlyobsoleted)
  outputpofile.write(str(outputpo))
  return 1

def main(argv=None):
  from translate.convert import convert
  formats = {"pot": ("po", convertpot), ("pot", "po"): ("po", convertpot)}
  parser = convert.ConvertOptionParser(formats, usepots=True, usetemplates=True, 
          allowmissingtemplate=True, description=__doc__)
  parser.add_option("", "--tm", dest="tm", default=None,
    help="The file to use as translation memory when fuzzy matching")
  parser.passthrough.append("tm")
  defaultsimilarity=75
  parser.add_option("-s", "--similarity", dest="min_similarity", default=defaultsimilarity,
    type="float", help="The minimum similarity for inclusion (default: %d%%)" % defaultsimilarity)
  parser.passthrough.append("min_similarity")
  parser.add_option("--nofuzzymatching", dest="fuzzymatching", action="store_false", 
          default=True, help="Disable fuzzy matching")
  parser.passthrough.append("fuzzymatching")
  parser.run(argv)


if __name__ == '__main__':
    main()
