#!/usr/bin/python
# -*- coding: utf-8 -*-

#  Copyright © 2009, 2011-2012  B. Clausius <barcc@gmx.de>
#
#  This program 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 3 of the License, or
#  (at your option) any later version.
#
#  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.

from glob import glob
import os
import sys
import re

import distutils

from distutils.core import setup
import distutils.cmd
from distutils.extension import Extension

from distutils.errors import DistutilsOptionError

from distutils.dir_util import remove_tree
from distutils.log import warn, info, error, fatal, debug

import distutils.command.build
import distutils.command.build_ext
import distutils.command.install
import distutils.command.install_data
import distutils.command.clean

#from Pyrex.Distutils.extension import Extension
#from Pyrex.Distutils import build_ext
#from Cython.Distutils import build_ext

from pybiklib import config


############ This code is taken from python-distutils-extra
class build_i18n(distutils.cmd.Command):

    description = "integrate the gettext framework"
    
    user_options = [
        ('desktop-files=',  None, '.desktop.in files that should be merged'),
        ('xml-files=',      None, '.xml.in files that should be merged'),
        ('schemas-files=',  None, '.schemas.in files that should be merged'),
        ('key-files=',      None, '.key.in files that should be merged'),
        ('domain=',         'd',  'gettext domain'),
        ('merge-po',        'm',  'merge po files against template'),
        ('po-dir=',         'p',  'directory that holds the i18n files'),
        ('bug-contact=',    None, 'contact address for msgid bugs')]
        
    boolean_options = ['merge-po']
    
    def initialize_options(self):
        self.desktop_files = []
        self.xml_files = []
        self.key_files = []
        self.schemas_files = []
        self.domain = None
        self.merge_po = False
        self.bug_contact = None
        self.po_dir = None
        
    def finalize_options(self):
        if self.domain is None:
            self.domain = self.distribution.metadata.name
        if self.po_dir is None:
            self.po_dir = "po"
            
    def run(self):
        """
        Update the language files, generate mo files and add them
        to the to be installed files
        """
        data_files = self.distribution.data_files
        
        if self.bug_contact is not None:
            os.environ["XGETTEXT_ARGS"] = "--msgid-bugs-address=%s " % \
                                          self.bug_contact
                                          
        # Print a warning if there is a Makefile that would overwrite our
        # values
        if os.path.exists("%s/Makefile" % self.po_dir):
            self.announce("""
WARNING: Intltool will use the values specified from the
         existing po/Makefile in favor of the vaules
         from setup.cfg.
         Remove the Makefile to avoid problems.""")
         
        # Update po(t) files and print a report
        # We have to change the working dir to the po dir for intltool
        cmd = ["intltool-update", (self.merge_po and "-r" or "-p"), "-g", self.domain]
        wd = os.getcwd()
        try:
            for target, files in data_files:
                for f in files:
                    if f.endswith('.script'):
                        self.spawn(['tools/conv-plugin-for-translation.py', f])
            os.chdir(self.po_dir)
            self.spawn(cmd)
        finally:
            os.chdir(wd)
            for target, files in data_files:
                for f in files:
                    if f.endswith('.script') and os.path.isfile(f+'.py'):
                        os.remove(f+'.py')
                        
        for po_file in glob("%s/*.po" % self.po_dir):
            lang = os.path.basename(po_file[:-3])
            mo_dir =  os.path.join("build", "mo", lang, "LC_MESSAGES")
            mo_file = os.path.join(mo_dir, "%s.mo" % self.domain)
            if not os.path.exists(mo_dir):
                os.makedirs(mo_dir)
            cmd = ["msgfmt", po_file, "-o", mo_file]
            self.spawn(cmd)
            
            targetpath = os.path.join("share/locale", lang, "LC_MESSAGES")
            data_files.append((targetpath, (mo_file,)))
            
            # create translated manpage
            man_dir = os.path.join('build','man',lang)
            man_file = os.path.join(man_dir,'pybik.6')
            if not os.path.exists(man_dir):
                os.makedirs(man_dir)
            self.spawn(['./tools/create_manpage.py', man_file, 'build/mo', lang])
            import subprocess
            result = subprocess.call(['cmp', '--silent', man_file, os.path.join('build','man','pybik.6')])
            if result:
                # only install translated manpages
                data_files.append(('share/man/'+lang+'/man6', [man_file]))
            
            
        # merge .in with translation
        for (option, switch) in ((self.xml_files, "-x"),
                                 (self.desktop_files, "-d"),
                                 (self.schemas_files, "-s"),
                                 (self.key_files, "-k"),):
            try:
                file_set = eval(option)
            except:
                continue
            for (target, files) in file_set:
                build_target = os.path.join("build", target)
                if not os.path.exists(build_target):
                    os.makedirs(build_target)
                files_merged = []
                for f in files:
                    if f.endswith(".in"):
                        file_merged = os.path.basename(f[:-3])
                    else:
                        file_merged = os.path.basename(f)
                    file_merged = os.path.join(build_target, file_merged)
                    cmd = ["intltool-merge", switch, self.po_dir, f,
                           file_merged]
                    self.spawn(cmd)
                    files_merged.append(file_merged)
                data_files.append((target, files_merged))
                
#####################

def py2pyx(infile, outfile):
    info('py2pyx: %s --> %s' % (infile, outfile))
    os.system('python tools/py2pyx.py %s %s' % (infile, outfile))
def py2pxd(infile, outfile):
    info('py2pxd: %s --> %s' % (infile, outfile))
    os.system('tools/py2pxd.py %s %s' % (infile, outfile))
def pyrex(self, infile, outfile):
    info('pyrex: %s --> %s' % (infile, outfile))
    self.spawn(["pyrexc", infile])
def cython(self, infile, outfile):
    info('cython: %s --> %s' % (infile, outfile))
    self.spawn(["cython", '-o', outfile, infile])
    
    
class build_ext (distutils.command.build_ext.build_ext):
    user_options = distutils.command.build_ext.build_ext.user_options + [
                            ('cython',None,'Use Cython to compile pyx-files'),
                            ('pyrex',None,'Use pyrex to compile pyx-files')]
    def __init__(self, *args):
        self.cython = None
        self.pyrex = None
        distutils.command.build_ext.build_ext.__init__(self, *args)
        
    def finalize_options(self):
        distutils.command.build_ext.build_ext.finalize_options(self)
        if self.cython is None:
            if self.pyrex is None:
                # Default Value
                self.cython = True
            else:
                self.cython = not self.pyrex
        else:
            if self.pyrex is None:
                self.cython = bool(self.cython)
            else:
                raise DistutilsOptionError('Option pyrex and cython conflicts')
        del self.pyrex
        
    def swig_sources(self, sources, extension):
        in_files = sources + extension.depends
        pyx_files = []
        pyx_files_dep = []
        for in_file in in_files:
            out_files = pyx_files if in_file in sources else pyx_files_dep
            if in_file.endswith('.py'):
                out_file = os.path.join(self.build_temp, in_file[:-3]+'_c.py')
                out_file2 = os.path.join(self.build_temp, in_file[:-3]+'_c.pxd')
                self.mkpath(os.path.dirname(out_file))
                self.make_file(in_files, out_file, py2pyx, (in_file, out_file))
                self.make_file(in_files, out_file2, py2pxd, (in_file, out_file2))
                pyx_files_dep.append(out_file2)
            elif in_file.endswith(('.pxi','.pxd')):
                out_file = os.path.join(self.build_temp, in_file)
                self.mkpath(os.path.dirname(out_file))
                self.copy_file(in_file, out_file)
            else:
                out_file = in_file
            out_files.append(out_file)
        out_files = []
        for in_file in pyx_files:
            if in_file.endswith('.py'):
                out_file = in_file[:-3]+'.c'
                self.make_file(pyx_files+pyx_files_dep, out_file,
                                cython if self.cython else pyrex, (self, in_file, out_file))
                out_files.append(out_file)
            else:
                out_files.append(in_file)
        return distutils.command.build_ext.build_ext.swig_sources(self, out_files, extension)
        
        
class build_man (distutils.cmd.Command):
    description = "build the manpage"
    user_options = []
    def run(self):
        data_files = self.distribution.data_files
        man_dir = os.path.join('build', 'man')
        man_file = os.path.join(man_dir, 'pybik.6')
        if not os.path.exists(man_dir):
            os.makedirs(man_dir)
        self.spawn(['./tools/create_manpage.py', man_file])
        data_files.append(('share/man/man6', [man_file]))
    def initialize_options(self): pass
    def finalize_options(self): pass
        
class build(distutils.command.build.build):
    """Adds extra commands to the build target."""
    def finalize_options(self):
        distutils.command.build.build.finalize_options(self)
        self.sub_commands.append(("build_man", lambda cmd: True))
        self.sub_commands.append(("build_i18n", lambda cmd: True))
        
        
class install (distutils.command.install.install):
    def run(self):
        filename = os.path.join(os.path.dirname(__file__), 'pybiklib', 'config.py')
        tmpfile = filename + '.orig'
        if self.install_layout == 'deb':
            datadir = os.path.join(self.prefix, 'share')
        else:
            datadir = os.path.join(self.install_data, 'share')
        appdatadir = os.path.join(datadir, 'pybik')
        os.rename(filename, tmpfile)
        try:
            try:
                with open(tmpfile, 'r') as file_in, open(filename, 'w') as file_out:
                    for line in file_in:
                        line = re.sub(r'^(data_dir\s*=\s*).*$',
                                      r'\1' + repr(datadir),
                                      line)
                        line = re.sub(r'^(appdata_dir\s*=\s*).*$',
                                      r'\1' + repr(appdatadir),
                                      line)
                        file_out.write(line)
                    file_out.flush()
            except (OSError, IOError) as e:
                print e
                sys.exit(1)
            distutils.command.install.install.run(self)
        finally:
            os.rename(tmpfile, filename)
            
            
class clean (distutils.command.clean.clean):
    def run(self):
        if self.all:
            for _dir in ['mo', 'man']:
                _dir = os.path.join('build', _dir)
                if os.path.exists(_dir):
                    remove_tree(_dir, dry_run=self.dry_run, verbose=self.verbose)
                else:
                    debug("'%s' does not exist -- can't clean it", _dir)
            _file = 'po/pybik.pot'
            if os.path.exists(_file):
                if self.verbose >= 1:
                    info("removing '%s'", _file)
                if not self.dry_run:
                    os.remove(_file)
            else:
                debug("'%s' does not exist -- can't clean it", _file)
        distutils.command.clean.clean.run(self)
        
        
setup(  name=config.PACKAGE,
        version=config.VERSION,
        description='Pybik - the magic cube',
        author=config.AUTHORS[0],
        author_email=config.CONTACT,
        url=config.WEBSITE,
        license=config.LICENSE_NAME,
        scripts=['pybik'],
        data_files=[
                        ('share/applications', ['data/applications/pybik.desktop']),
                        ('share/pixmaps', ['data/pixmaps/pybik.png']),
                        ('share/pybik/ui', glob('data/ui/*')),
                        ('share/pybik/scripts', glob('data/scripts/*.py')),
                        ('share/pybik/scripts', glob('data/scripts/*.script')),
                    ],
        ext_modules=[
                        Extension("pybiklib/drwBlock_c",
                                    ["pybiklib/drwBlock.py"],
                                    depends=["pybiklib/cube.py",
                                            "pybiklib/math.pxd",
                                            'pybiklib/gl.pxd'],
                                    libraries=['GL']),
                        Extension("pybiklib/cube_c",
                                    ["pybiklib/cube.py"],
                                    depends=["pybiklib/math.pxd",
                                            'pybiklib/gl.pxd'],
                                    libraries=['GL']),
                        Extension("pybiklib/glarea_common_c",
                                    ["pybiklib/glarea_common.py"],
                                    depends=["pybiklib/math.pxd",
                                            "pybiklib/glu.pxd",
                                            'pybiklib/gl.pxd'],
                                    libraries=['GL', 'GLU']),
                    ],
        packages=['pybiklib'],
        package_dir={'pybiklib': 'pybiklib',},
        cmdclass={
                    'build_ext': build_ext,
                    'build_i18n': build_i18n,
                    'build_man': build_man,
                    'build': build,
                    'install_data': distutils.command.install_data.install_data,
                    'install': install,
                    'clean': clean,
                },
     )
     
