#!/usr/bin/env python
#
# 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

from pootle_app.models import store_file
from pootle import potree
from pootle import pootle
from translate.storage import po
from translate.search import indexing
import os
import profile
import pstats

class PootleBenchmarker:
    """class to aid in benchmarking pootle"""
    StoreClass = store_file.store_file
    UnitClass = store_file.pootleunit
    def __init__(self, test_dir):
        """sets up benchmarking on the test directory"""
        self.test_dir = os.path.abspath(test_dir)
        self.project_dir = os.path.join(self.test_dir, "benchmark")
        self.po_dir = os.path.join(self.project_dir, "zxx")

    def clear_test_dir(self):
        """removes the given directory"""
        if os.path.exists(self.test_dir):
            for dirpath, subdirs, filenames in os.walk(self.test_dir, topdown=False):
                for name in filenames:
                    os.remove(os.path.join(dirpath, name))
                for name in subdirs:
                    os.rmdir(os.path.join(dirpath, name))
        if os.path.exists(self.test_dir):
            os.rmdir(self.test_dir)
        assert not os.path.exists(self.test_dir)

    def setup_server(self):
        """gets a pootle server"""
        cwd = os.path.abspath(os.path.curdir)
        parser = pootle.PootleOptionParser()
        prefsfile = os.path.join(self.test_dir, "pootle.prefs")
        pootleprefsstr = """
importmodules.pootleserver = 'Pootle.pootle'
Pootle:
  serverclass = pootleserver.PootleServer
  sessionkey = 'dummy'
  userprefs = "users.prefs"
  podirectory = "%s"
  projects.benchmark:
    fullname = "Benchmark"
    description = "Benchmark auto-created files"
    checkstyle = "standard"
    localfiletype = "po"
  languages.zxx.fullname = "Test Language"
""" % (self.test_dir)
        open(prefsfile, "w").write(pootleprefsstr)
        userprefsfile = os.path.join(self.test_dir, "users.prefs")
        open(userprefsfile, "w").write("testuser.activated=1\ntestuser.passwdhash = 'dd82c1882969461de74b46427961ea2c'\n")
        options, args = parser.parse_args(["--prefsfile=%s" % prefsfile])
        options.servertype = "dummy"
        self.server = parser.getserver(options)
        os.chdir(cwd)
        return self.server

    def get_session(self):
        """gets a new session object"""
        return users.PootleSession(self.server.sessioncache, self.server)

    def create_sample_files(self, num_dirs, files_per_dir, strings_per_file, source_words_per_string, target_words_per_string):
        """creates sample files for benchmarking"""
        if not os.path.exists(self.test_dir):
            os.mkdir(self.test_dir)
        if not os.path.exists(self.project_dir):
            os.mkdir(self.project_dir)
        if not os.path.exists(self.po_dir):
            os.mkdir(self.po_dir)
        for dirnum in range(num_dirs):
            if num_dirs > 1:
                dirname = os.path.join(self.po_dir, "sample_%d" % dirnum)
                if not os.path.exists(dirname):
                    os.mkdir(dirname)
            else:
                dirname = self.po_dir
            for filenum in range(files_per_dir):
                sample_file = self.StoreClass(pofilename=os.path.join(dirname, "file_%d.po" % filenum))
                for stringnum in range(strings_per_file):
                    source_string = " ".join(["word%d" % i for i in range(source_words_per_string)])
                    sample_unit = sample_file.addsourceunit(source_string)
                    sample_unit.target = " ".join(["drow%d" % i for i in range(target_words_per_string)])
                sample_file.savepofile()

    def parse_po_files(self):
        """parses all the po files in the test directory into memory"""
        count = 0
        for dirpath, subdirs, filenames in os.walk(self.po_dir, topdown=False):
            for name in filenames:
                pofilename = os.path.join(dirpath, name)
                parsedfile = po.pofile(open(pofilename, 'r'))
                count += len(parsedfile.units)
        print "counted %d units" % count

    def parse_and_create_stats(self):
        """parses all the po files in the test directory into memory, using store_file, which creates Stats"""
        count = 0
        indexing.HAVE_INDEXER = False
        for dirpath, subdirs, filenames in os.walk(self.po_dir, topdown=False):
            for name in filenames:
                pofilename = os.path.join(dirpath, name)
                parsedfile = store_file.store_file(pofilename=pofilename)
                count += len(parsedfile.units)
        print "stats on %d units" % count

    def parse_and_create_index(self):
        """parses all the po files in the test directory into memory, using store_file, and allow index creation"""
        count = 0
        indexing.HAVE_INDEXER = True
        self.server.potree.projectcache.clear()
        project = self.server.potree.getproject("zxx", "benchmark")
        for name in project.browsefiles():
            count += len(project.getpofile(name).units)
        print "indexed %d units" % count
        assert os.path.exists(os.path.join(self.po_dir, ".poindex-%s-%s" % (project.projectcode, project.languagecode)))

    def generate_main_page(self):
        """tests generating the main page"""
        session = self.get_session()
        page = self.server.getpage(["index.html"], session, {})
        print page.templatevars

    def generate_projectindex_page(self):
        """tests generating the index page for the project"""
        session = self.get_session()
        assert self.server.potree.haslanguage("zxx")
        assert self.server.potree.hasproject("zxx", "benchmark")
        page = self.server.getpage(["zxx", "benchmark"], session, {})
        print page.templatevars

    def generate_translation_page(self):
        """tests generating the translation page for the file"""
        session = self.get_session()
        page = self.server.getpage(["zxx", "benchmark", "translate.html"], session, {})
        print page.templatevars

    def submit_translation_change(self):
        """tests generating the translation page for the file"""
        session = self.get_session()
        project = self.server.potree.getproject("zxx", "benchmark")
        project.setrights(None, ["view", "translate"])
        pofilename = project.browsefiles()[0]
        args = {"pofilename": pofilename, "submit0": "true", "trans0": "changed"}
        page = self.server.getpage(["zxx", "benchmark", "translate.html"], session, args)
        pofile = project.getpofile(pofilename)
        print str(pofile.getitem(0))
        # assert fails because of multistring
        # assert pofile.getitem(0).unquotedmsgstr == "changed"
        print page.templatevars

if __name__ == "__main__":
    for sample_file_sizes in [
      # num_dirs, files_per_dir, strings_per_file, source_words_per_string, target_words_per_string
      # (1, 1, 1, 1, 1),
      (1, 1, 30, 10, 10),
      # (1, 5, 10, 10, 10),
      (1, 10, 10, 10, 10),
      (5, 10, 10, 10, 10),
      # (5, 10, 100, 20, 20),
      # (10, 20, 100, 10, 10),
      ]:
        benchmarker = PootleBenchmarker("BenchmarkDir")
        benchmarker.clear_test_dir()
        benchmarker.create_sample_files(*sample_file_sizes)
        benchmarker.setup_server()
        methods = ["parse_po_files", "parse_and_create_stats", "parse_and_create_index",
                   "generate_main_page", "generate_projectindex_page", "generate_translation_page",
                   "submit_translation_change",
                  ]
        for methodname in methods:
            print methodname, "%d dirs, %d files, %d strings, %d/%d words" % sample_file_sizes
            print "_______________________________________________________"
            statsfile = methodname + '_%d_%d_%d_%d_%d.stats' % sample_file_sizes
            profile.run('benchmarker.%s()' % methodname, statsfile)
            stats = pstats.Stats(statsfile)
            stats.sort_stats('cumulative').print_stats(20)
            print "_______________________________________________________"
        benchmarker.clear_test_dir()
