# Requires Python 2.4 or better and win32api.

"""Config on Msys mingw

This version expects the Pygame 1.9.0 dependencies as built by
msys_build_deps.py
"""

import dll
from setup_win_common import get_definitions
import msys
import os, sys, string
import logging
from glob import glob
from distutils.sysconfig import get_python_inc

configcommand = os.environ.get('SDL_CONFIG', 'sdl-config',)
configcommand = configcommand + ' --version --cflags --libs'
localbase = os.environ.get('LOCALBASE', '')

#these get prefixes with '/usr/local' and /mingw or the $LOCALBASE
origincdirs = ['/include', '/include/SDL', '/include/SDL11',
               '/include/libpng12', ]
origlibdirs = ['/lib']


class ConfigError(Exception):
    pass

def path_join(a, *p):
    return os.path.join(a, *p).replace(os.sep, '/')
path_split = os.path.split

def print_(*args, **kwds):
    return msys.msys_print(*args, **kwds)

class DependencyProg:
    needs_dll = True
    def __init__(self, name, envname, exename, minver, msys, defaultlibs=None):
        if defaultlibs is None:
            defaultlibs = [dll.name_to_root(name)]
        self.name = name
        try:
            command = os.environ[envname]
        except KeyError:
            command = exename
        else:
            drv, pth = os.path.splitdrive(command)
            if drv:
                command = '/' + drv[0] + pth
        self.lib_dir = ''
        self.inc_dir = ''
        self.libs = []
        self.cflags = ''
        try:
            config = msys.run_shell_command([command, '--version', '--cflags', '--libs'])
            ver, flags = config.split('\n', 1)
            self.ver = ver.strip()
            flags = flags.split()
            if minver and self.ver < minver:
                err= 'WARNING: requires %s version %s (%s found)' % (self.name, self.ver, minver)
                raise ValueError(err)
            self.found = 1
            self.cflags = ''
            for f in flags:
                if f[:2] in ('-I', '-L'):
                    self.cflags += f[:2] + msys.msys_to_windows(f[2:]) + ' '
                elif f[:2] in ('-l', '-D'):
                    self.cflags += f + ' '
                elif f[:3] == '-Wl':
                    self.cflags += '-Xlinker ' + f + ' '
        except ValueError:
            print_('WARNING: "%s" failed!' % command)
            self.found = 0
            self.ver = '0'
            self.libs = defaultlibs

    def configure(self, incdirs, libdir):
        if self.found:
            print_(self.name + '        '[len(self.name):] + ': found ' + self.ver)
            self.found = 1
        else:
            print_(self.name + '        '[len(self.name):] + ': not found')

class Dependency:
    needs_dll = True
    def __init__(self, name, checkhead, checklib, libs=None):
        if libs is None:
            libs = [dll.name_to_root(name)]
        self.name = name
        self.inc_dir = None
        self.lib_dir = None
        self.libs = libs
        self.found = 0
        self.checklib = checklib
        self.checkhead = checkhead
        self.cflags = ''

    def configure(self, incdirs, libdirs):
        self.find_inc_dir(incdirs)
        self.find_lib_dir(libdirs)

        if self.lib_dir and self.inc_dir:
            print_(self.name + '        '[len(self.name):] + ': found')
            self.found = 1
        else:
            print_(self.name + '        '[len(self.name):] + ': not found')

    def find_inc_dir(self, incdirs):
        incname = self.checkhead
        for dir in incdirs:
            path = path_join(dir, incname)
            if os.path.isfile(path):
                self.inc_dir = dir
                return

    def find_lib_dir(self, libdirs):
        libname = self.checklib
        for dir in libdirs:
            path = path_join(dir, libname)
            if any(map(os.path.isfile, glob(path+'*'))):
                self.lib_dir = dir
                return


class DependencyPython:
    needs_dll = False
    def __init__(self, name, module, header):
        self.name = name
        self.lib_dir = ''
        self.inc_dir = ''
        self.libs = []
        self.cflags = ''
        self.found = 0
        self.ver = '0'
        self.module = module
        self.header = header

    def configure(self, incdirs, libdirs):
        self.found = 1
        if self.module:
            try:
                self.ver = __import__(self.module).__version__
            except ImportError:
                self.found = 0
        if self.found and self.header:
            fullpath = path_join(get_python_inc(0), self.header)
            if not os.path.isfile(fullpath):
                self.found = 0
            else:
                self.inc_dir = os.path.split(fullpath)[0]
        if self.found:
            print_(self.name + '        '[len(self.name):] + ': found', self.ver)
        else:
            print_(self.name + '        '[len(self.name):] + ': not found')

class DependencyDLL:
    needs_dll = False
    def __init__(self, name, libs=None):
        if libs is None:
            libs = dll.libraries(name)
        self.name = 'COPYLIB_' + dll.name_to_root(name)
        self.inc_dir = None
        self.lib_dir = '_'
        self.libs = libs
        self.found = 1  # Alway found to make its COPYLIB work
        self.cflags = ''
        self.lib_name = name
        self.file_name_test = dll.tester(name)

    def configure(self, incdirs, libdirs, start=None):
        omit = []
        if start is not None:
            if self.set_path(start):
                return
            omit.append(start)
            p, f = path_split(start)
            if f == 'lib' and self.set_path(path_join(p, 'bin')):
                return
            omit.append(start)
        # Search other directories
        for dir in libdirs:
            if dir not in omit:
                if self.set_path(dir):
                    return
                p, f = path_split(dir)
                if f == 'lib' and self.set_path(path_join(p, 'bin')):  # cond. and
                    return

    def set_path(self, wdir):
        test = self.file_name_test
        try:
            files = os.listdir(wdir)
        except OSError:
            pass
        else:
            for f in files:
                if test(f) and os.path.isfile(path_join(wdir, f)):
                    # Found
                    self.lib_dir = path_join(wdir, f)
                    return True
        # Not found
        return False

class DependencyWin:
    needs_dll = False
    def __init__(self, name, cflags):
        self.name = name
        self.inc_dir = None
        self.lib_dir = None
        self.libs = []
        self.found = 1
        self.cflags = cflags

    def configure(self, incdirs, libdirs):
        pass


def main():
    m = msys.Msys(require_mingw=False)
    print_('\nHunting dependencies...')
    DEPS = [
        DependencyProg('SDL', 'SDL_CONFIG', 'sdl-config', '1.2.13', m),
        Dependency('FONT', 'SDL_ttf.h', 'libSDL_ttf.dll.a'),
        Dependency('IMAGE', 'SDL_image.h', 'libSDL_image.dll.a'),
        Dependency('MIXER', 'SDL_mixer.h', 'libSDL_mixer.dll.a'),
        Dependency('PNG', 'png.h', 'libpng.dll.a'),
        Dependency('JPEG', 'jpeglib.h', 'libjpeg.dll.a'),
        Dependency('PORTMIDI', 'portmidi.h', 'libportmidi.dll.a'),
        Dependency('PORTTIME', 'portmidi.h', 'libportmidi.dll.a'),
        DependencyDLL('TIFF'),
        DependencyDLL('VORBISFILE'),
        DependencyDLL('VORBIS'),
        DependencyDLL('OGG'),
        DependencyDLL('FREETYPE'),
        DependencyDLL('Z'),
    ]

    if not DEPS[0].found:
        print_('Unable to run "sdl-config". Please make sure a development version of SDL is installed.')
        sys.exit(1)

    if localbase:
        incdirs = [localbase+d for d in origincdirs]
        libdirs = [localbase+d for d in origlibdirs]
    else:
        incdirs = []
        libdirs = []
    incdirs += [m.msys_to_windows("/usr/local"+d) for d in origincdirs]
    libdirs += [m.msys_to_windows("/usr/local"+d) for d in origlibdirs]
    if m.mingw_root is not None:
        incdirs += [m.msys_to_windows("/mingw"+d) for d in origincdirs]
        libdirs += [m.msys_to_windows("/mingw"+d) for d in origlibdirs]
    for arg in string.split(DEPS[0].cflags):
        if arg[:2] == '-I':
            incdirs.append(arg[2:])
        elif arg[:2] == '-L':
            libdirs.append(arg[2:])
    dll_deps = []
    for d in DEPS:
        d.configure(incdirs, libdirs)
        if d.needs_dll:
            dll_dep = DependencyDLL(d.name)
            dll_dep.configure(incdirs, libdirs, d.lib_dir)
            dll_deps.append(dll_dep)

    DEPS += dll_deps
    for d in get_definitions():
        DEPS.append(DependencyWin(d.name, d.value))
    for d in DEPS:
        if isinstance(d, DependencyDLL):
            if d.lib_dir == '':
                print_("DLL for %-12s: not found" % d.lib_name)
            else:
                print_("DLL for %-12s: %s" % (d.lib_name, d.lib_dir))

    for d in DEPS[1:]:
        if not d.found:
            if "-auto" not in sys.argv:
                logging.warning(
                    "Some pygame dependencies were not found. "
                    "Pygame can still compile and install, but games that "
                    "depend on those missing dependencies will not run. "
                    "Use -auto to continue building without all dependencies. "
                )
                raise SystemExit("Missing dependencies")
            break

    return DEPS

if __name__ == '__main__':
    print_("""This is the configuration subscript for MSYS.
Please run "config.py" for full configuration.""")

