# Copyright (c) 2011 Tencent Inc.
# All rights reserved.
#
# Author: Michaelpeng <michaelpeng@tencent.com>
# Date:   January 09, 2012


"""
 This is the configuration parse module which parses
 the BLADE_ROOT as a configuration file.

"""
import os
import sys
import traceback

import console
from blade_util import var_to_list
from cc_targets import HEAP_CHECK_VALUES


# Global config object
blade_config = None


def config_items(**kwargs):
    """Used in config functions for config file, to construct a appended
    items dict, and then make syntax more pretty
    """
    return kwargs


class BladeConfig(object):
    """BladeConfig. A configuration parser class. """
    def __init__(self, current_source_dir):
        self.current_source_dir = current_source_dir
        self.current_file_name = ''
        self.configs = {
            'global_config' : {
                'build_path_template': 'build${m}_${profile}',
                'duplicated_source_action': 'warning', # Can be 'warning', 'error', 'none'
            },

            'cc_test_config': {
                'dynamic_link': False,
                'heap_check': '',
                'gperftools_libs': [],
                'gperftools_debug_libs': [],
                'gtest_libs': [],
                'gtest_main_libs': []
            },

            'cc_binary_config': {
                'extra_libs': []
            },

            'distcc_config': {
                'enabled': False
            },

            'link_config': {
                'link_on_tmp': False,
                'enable_dccc': False
            },

            'java_config': {
                'source_version': '',
                'target_version': ''
            },

            'thrift_config': {
                'thrift': 'thrift',
                'thrift_libs': [],
                'thrift_incs': [],
            },

            'fbthrift_config': {
                'fbthrift1': 'thrift1',
                'fbthrift2': 'thrift2',
                'fbthrift_libs': [],
                'fbthrift_incs': [],
            },

            'proto_library_config': {
                'protoc': 'thirdparty/protobuf/bin/protoc',
                'protobuf_libs': [],
                'protobuf_path': '',
                'protobuf_incs': [],
                'protobuf_php_path': '',
                'protoc_php_plugin': '',
            },

            'cc_config': {
                'extra_incs': [],
                'cppflags': [],
                'cflags': [],
                'cxxflags': [],
                'linkflags': [],
                'c_warnings': [],
                'cxx_warnings': [],
                'warnings': [],
                'cpplint': 'cpplint.py',
                'optimize': [],
                'benchmark_libs': [],
                'benchmark_main_libs': [],
            }
        }

    def _try_parse_file(self, filename):
        """load the configuration file and parse. """
        try:
            self.current_file_name = filename
            if os.path.exists(filename):
                execfile(filename)
        except SystemExit:
            console.error_exit('Parse error in config file %s, exit...' % filename)

    def parse(self):
        """load the configuration file and parse. """
        self._try_parse_file(os.path.join(os.path.dirname(sys.argv[0]), 'blade.conf'))
        self._try_parse_file(os.path.expanduser('~/.bladerc'))
        self._try_parse_file(os.path.join(self.current_source_dir, 'BLADE_ROOT'))

    def update_config(self, section_name, append, user_config):
        """update config section by name. """
        config = self.configs.get(section_name, {})
        if config:
            if append:
                self._append_config(section_name, config, append)
            self._replace_config(section_name, config, user_config)
        else:
            console.error('%s: %s: unknown config section name' % (
                          self.current_file_name, section_name))

    def _append_config(self, section_name, config, append):
        """Append config section items"""
        if not isinstance(append, dict):
            console.error('%s: %s: append must be a dict' %
                    (self.current_file_name, section_name))
        else:
            for k in append:
                if k in config:
                    if isinstance(config[k], list):
                        config[k] += var_to_list(append[k])
                    else:
                        console.warning('%s: %s: config item %s is not a list' %