###############################################################################
#                                                                             #
# Copyright (C) 2011-2014 Edward d'Auvergne                                   #
#                                                                             #
# This file is part of the program relax (http://www.nmr-relax.com).          #
#                                                                             #
# 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/>.       #
#                                                                             #
###############################################################################

# Module docstring.
"""This script is used to build relax as an application on certain platforms.

The Mac OS X component was initially generated by py2applet, but has been highly modified.  To use this script to build a Mac app, the following command needs to be run:

Usage:

python setup.py py2app


To then create a DMG file for installation, type:

hdiutil create -fs HFS+ -volname "relax" -srcfolder dist/relax.app relax.dmg
"""

# Python module import.
from os import getcwd, sep, walk
from os.path import relpath, sep
from re import search
try:
    from setuptools import setup
except ImportError:
    print("ImportError:  To run setup.py, please installed the Python setuptools (see http://pypi.python.org/pypi/setuptools)")
    setup = None
import sys

# relax module imports.
from lib.errors import RelaxError
from status import Status; status = Status()
from version import version_full


class Setup:
    """Class containing setuptools targets for different platforms."""

    def __init__(self):
        """Initialise and execute."""

        # The extension.
        extension = sys.argv[1]

        # Mac OS X application.
        if extension == 'py2app':
            self.mac_setup()

        # Unsupported platform.
        else:
            raise RelaxError("The setuptools extension '%s' is not supported yet." % extension)

        # Generic setup args.
        self.args_generic()

        # Execute the setuptools setup() method to actually do something.
        setup(
            app=self.APP,
            name=self.NAME,
            version=self.VERSION,
            data_files=self.DATA_FILES,
            options=self.OPTIONS,
            setup_requires=self.REQUIRES
        )


    def args_generic(self):
        """Set up the arguments which are independent of the target."""

        # Get a list of data files.
        self.DATA_FILES = self.get_data_files()
        #for i in range(len(self.DATA_FILES)):
        #    print(self.DATA_FILES[i])
        #sys.exit(1)

        # Get the includes.
        self.INCLUDES = self.get_includes()
        #for i in range(len(self.INCLUDES)):
        #    print(self.INCLUDES[i])
        #sys.exit(1)


    def get_data_files(self):
        """Collect and return a list of data files.

        @return:    The list of data files as full paths.
        @rtype:     list of str
        """

        # Blacklisted files and directories.
        blacklist_dir = [
            'build',
            'dist'
        ]
        blacklist_files = [
        ]

        # All files and directories.
        data_files = []
        cwd = getcwd()
        for (dirpath, dirnames, filenames) in walk(cwd):
            # Skip .svn directories.
            split_path = dirpath.split(sep)
            if '.svn' in split_path:
                continue

            # Skip blacklisted directories.
            skip = False
            for dir_name in blacklist_dir:
                if dir_name in split_path:
                    skip = True
            if skip:
                continue

            # The relative path.
            rel_path = relpath(dirpath, cwd)

            # Loop over the files.
            file_list = []
            for file in filenames:
                # Skip names starting with '.'.
                if search('^\.', file):
                    continue

                # Blacklist.
                if file in blacklist_files:
                    continue

                # Append the file with path to the list.
                file_list.append("%s%s%s" % (rel_path, sep, file))

            # Append a tuple of the destination directory and the files.
            data_files.append((rel_path, file_list))

        # Return the data files.
        return data_files


    def get_includes(self):
        """Collect and return a list of modules to include.

        @return:    The list of modules.
        @rtype:     list of str
        """

        # Blacklisted files and directories.
        blacklist_dir = [
            'build',
            'dist',
            'bmrblib'+sep+'html_dictionary',
            'graphics',
            'sample_scripts',
            'scripts',
            'test_suite'+sep+'system_tests'+sep+'scripts',
            'test_suite'+sep+'shared_data'
        ]
        blacklist_files = [
        ]
        
        # Whitelisted directories.
        whitelist_dir = [
            'test_suite'+sep+'shared_data'+sep+'frame_order'+sep+'cam'
        ]

        # All files and directories.
        includes = []
        cwd = getcwd()
        for (dirpath, dirnames, filenames) in walk(cwd):
            # Skip .svn directories.
            split_path = dirpath.split(sep)
            if '.svn' in split_path:
                continue

            # The relative path.
            rel_path = relpath(dirpath, cwd)

            # Skip blacklisted directories.
            skip = False
            for dir_name in blacklist_dir:
                if search(dir_name, rel_path) and rel_path not in whitelist_dir:
                    skip = True
            if skip:
                continue

            # The module path.
            if rel_path == '.':
                module_path = ''
            else:
                module_path = rel_path.replace(sep, '.')
                if module_path:
                    module_path += '.'

            # Loop over the files.
            for file in filenames:
                # Skip names starting with '.'.
                if search('^\.', file):
                    continue

                # Skip non-Python source files.
                if not search('\.py$', file):
                    continue

                # Blacklist.
                if file in blacklist_files:
                    continue

                # Append a tuple of the destination directory and the file.
                includes.append("%s%s" % (module_path, file[:-3]))

        # Return the data files.
        return includes


    def mac_setup(self):
        """Mac OS X setup."""

        # The relax settings.
        self.APP = ['relax_gui_mode.py']
        self.NAME = 'relax'
        self.VERSION = version_full()
        self.OPTIONS = {}
        self.OPTIONS['py2app'] = {
            'argv_emulation': False,
            'iconfile': status.install_path + sep + 'graphics' + sep + 'ulysses_shadowless_trans_128x128.icns',
            'packages': 'wx',
            'site_packages': True,
            'includes': self.get_includes(),
            'excludes': ['build', 'dist'],
            'plist': {
                'CFBundleName':                 'relax',
                'CFBundleShortVersionString':   version_full(),
                'CFBundleGetInfoString':        'relax %s' % version_full(),
                'CFBundleIdentifier':           'com.nmr-relax.relax'
            }
        }
        self.REQUIRES = ['py2app']


# Execute the main class.
if __name__ == '__main__':
    Setup()
