#! /usr/bin/env python
# encoding: utf-8

import os
import Utils
import Options
import commands
g_maxlen = 40
import shutil
import re
import Logs
import sys
from Constants import HEXVERSION
from Configure import ConfigurationError

# used by waf dist and waf build
VERSION='0.09.0'
APPNAME='guitarix'

good_faust_versions = ['0.9.10','0.9.17','0.9.22','0.9.23','0.9.24']

# these variables are mandatory ('/' are converted automatically)
srcdir = '.'
blddir = 'build'


# options defined for waf configure
def set_options(opt):
    opt.tool_options('compiler_cxx')

    comp = opt.add_option_group("Compiler / Linker flags")

    comp.add_option('--debug',
                    action='store_const',
                    default=False,
                    const=True,
                    help='set compiler flags for a debug build')

    comp.add_option('--cxxflags-release',
                    type='string',
                    default='-O3 -DNDEBUG',
                    dest='cxxflags_release',
                    help='additional C++ compiler flags for release version (not used if --debug) [Default: %default]')

    comp.add_option('--cxxflags-debug',
                    type='string',
                    default='-O2 -g -fstack-protector-all',
                    dest='cxxflags_debug',
                    help='additional C++ compiler flags for debug version (only used if --debug) [Default: %default]')

    comp.add_option('--cxxflags',
                    type='string',
                    default='-Wall -std=c++0x', # -fomit-frame-pointer -ffast-math -fstrength-reduce -mmmx -mfpmath=sse -DUSE_XMMINTRIN -pipe
                    dest='cxxflags',
                    help='C++ base compiler flags [Default: %default]')

    comp.add_option('--optimization',
                    action='store_const',
                    default=False, #'-fomit-frame-pointer -ffast-math -fstrength-reduce -pipe',
                    const=True,
                    help='C++ optimization compiler flags [Default: %default]')

    ladspa = opt.add_option_group("other options")

    ladspa.add_option('--ladspadir',
                    type='string',
                    help='LADSPA plugin directory [Default: <prefix>/lib/ladspa]')


def print_msg(msg, nl=True):
    if HEXVERSION > 0x10500:
        s = sys.stderr
    else:
        s = sys.stdout
    if nl:
        t = "\n"
    else:
        t = " "
    s.write(msg+t)

# a bit of waf display formatting
def display_msg(msg, status = None, color = None):
    sr = msg
    global g_maxlen
    g_maxlen = max(g_maxlen, len(msg))
    if status:
        print_msg("%s :" % msg.ljust(g_maxlen),False)
        Utils.pprint(color, status)
    else:
        print_msg("%s" % msg.ljust(g_maxlen))

def error_msg(msg):
    Utils.pprint('RED', msg)

def display_feature(msg, build):
    if build:
        display_msg(msg, "yes", 'CYAN')
    else:
        display_msg(msg, "no", 'YELLOW')

def append_optimization_flags(cxxflags):
    cpu_model = None
    x86_flags = None
    try:
        for line in file("/proc/cpuinfo"):
            if cpu_model is None:
                if line.startswith("model name"):
                    cpu_model = line.split(":",1)[1].strip()
            elif x86_flags is None:
                if line.startswith("flags"):
                    x86_flags = line.split(":",1)[1].strip()
            else:
                break
    except IOError:
        pass
    if cpu_model is None or x86_flags is None:
        display_msg("Checking CPU Architecture",
                    "cpu model not found in /proc/cpuinfo",
                    "YELLOW")
        return None
    model = cpu_model.split()
    arch = os.uname()[4]
    if "AMD" in model and "x86_64" in arch:
        cxxflags.append ("-march=K8")
    elif "AMD" in model and "Sempron" in model and "i686" in arch:
        cxxflags.append ("-march=native")
    elif "Geode" in model :
        cxxflags.append ("-march=geode")
    elif "Core" in model and "x86_64" in arch:
        cxxflags.append ("-march=core2")
    elif "i386" in arch:
        cxxflags.append ("-march=i386")
    elif "i486" in arch:
        cxxflags.append ("-march=i486")
    elif "i586" in arch:
        cxxflags.append ("-march=i586")
    elif "i686" in arch:
        cxxflags.append ("-march=i686")
    else:
        cxxflags.append ("-march=native")

    if "mmx" in x86_flags:
        cxxflags.append ("-mmmx")
    if "3dnow" in x86_flags:
        cxxflags.append ("-m3dnow")

    if "sse5" in x86_flags:
        cxxflags.append ("-msse5")
        cxxflags.append ("-mfpmath=sse")
    elif "sse4_2" in x86_flags:
        cxxflags.append ("-msse4.2")
        cxxflags.append ("-mfpmath=sse")
    elif "sse4_1" in x86_flags:
        cxxflags.append ("-msse4.1")
        cxxflags.append ("-mfpmath=sse")
    elif "ssse3" in x86_flags:
        cxxflags.append ("-mssse3")
        cxxflags.append ("-mfpmath=sse")
    elif "sse4" in x86_flags:
        cxxflags.append ("-msse4")
        cxxflags.append ("-mfpmath=sse")
    elif "sse3" in x86_flags:
        cxxflags.append ("-msse3")
        cxxflags.append ("-mfpmath=sse")
    elif "sse2" in x86_flags:
        cxxflags.append ("-msse2")
        cxxflags.append ("-mfpmath=sse")
        #cxxflags.append ("-DUSE_XMMINTRIN")
    elif "sse" in x86_flags:
        cxxflags.append ("-msse")
        cxxflags.append ("-mfpmath=sse")
        # cxxflags.append ("-DUSE_XMMINTRIN")

    if not Options.options.debug:
        cxxflags.append ("-fomit-frame-pointer")
    cxxflags.append ("-ftree-loop-linear")
    cxxflags.append ("-ffinite-math-only")
    cxxflags.append ("-fno-math-errno")
    cxxflags.append ("-fno-signed-zeros")
    #cxxflags.append ("-ffast-math") # quicker but doesn't seem to work (difference in sound output)
    #cxxflags.append ("-malign-double")
    cxxflags.append ("-fstrength-reduce")
    cxxflags.append ("-pipe")
    return cpu_model

# guitarix waf configuration
def configure(conf):
    # compiler
    conf.check_tool('compiler_cxx')
    cxx_version = conf.env["CC_VERSION"];
    conf.check(header_name='ladspa.h', mandatory=1)
    # convolver and resampler
  
    # defines for compilation
    conf.define('GX_VERSION', VERSION)
  
    # writing config.h
    conf.write_config_header('config.h')

    conf.define('LIBDIR', os.path.normpath(os.path.join(conf.env['PREFIX'], 'lib')))
    conf.define('LADSPADIR', os.path.normpath(os.path.join(conf.env['LIBDIR'], 'ladspa')))
    if Options.options.ladspadir:
        conf.env['LADSPADIR'] = Options.options.ladspadir

    # g++ flags
    cxxflags = Options.options.cxxflags.split()
    if Options.options.debug:
        cxxflags += Options.options.cxxflags_debug.split()
    else:
        cxxflags += Options.options.cxxflags_release.split()
    cpu_model = None
    if Options.options.optimization:
        cpu_model = append_optimization_flags(cxxflags)
    conf.env['CXXFLAGS'] = cxxflags

    # some output
    print
    display_msg("==================")
    version_msg = "GUITARIX " + VERSION
    print_msg(version_msg)

    print_msg("")

    # config subdirs
    conf.sub_config('ladspa');
 
  
    if cpu_model:
        display_msg("CPU version" , "%s" % cpu_model, "CYAN")
    display_msg("C++ flags", " ".join(conf.env['CXXFLAGS']), 'CYAN')
    #display_msg("Compiler %s version" %conf.env["CXX"], "%s" % ".".join(cxx_version), "CYAN")
    display_feature("Use faust", conf.env['FAUST'])
    display_msg("Install ladspa", conf.env['LADSPADIR'], 'CYAN')
    if conf.env['g++']:
       error_msg("ERROR       !!! Compiler version is to old !!!")

    print_msg("")

def build(bld):
    # process subfolders from here
    bld.add_subdirs('ladspa')
 
