# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import copy
import os

# NOTE: This has only been used to parse
# core/page/RuntimeEnabledFeatures.in and may not be capable
# of parsing other .in files correctly.

# .in file format is:
# // comment
# name1 arg=value, arg2=value2, arg2=value3
#
# InFile must be passed a dictionary of default values
# with which to validate arguments against known names.
# Sequence types as default values will produce sequences
# as parse results.
# Bare arguments (no '=') are treated as names with value True.
# The first field will always be labeled 'name'.
#
# InFile.load_from_files(['file.in'], {'arg': None, 'arg2': []})
#
# Parsing produces an array of dictionaries:
# [ { 'name' : 'name1', 'arg' :' value', arg2=['value2', 'value3'] }

def _is_comment(line):
    return line.startswith("//") or line.startswith("#")

class InFile(object):
    def __init__(self, lines, defaults, valid_values=None, default_parameters=None):
        self.name_dictionaries = []
        self.parameters = copy.deepcopy(default_parameters if default_parameters else {})
        self._defaults = defaults
        self._valid_values = copy.deepcopy(valid_values if valid_values else {})
        self._parse(map(str.strip, lines))

    @classmethod
    def load_from_files(self, file_paths, defaults, valid_values, default_parameters):
        lines = []
        for path in file_paths:
            with open(os.path.abspath(path)) as in_file:
                lines += in_file.readlines()
        return InFile(lines, defaults, valid_values, default_parameters)

    def _is_sequence(self, arg):
        return (not hasattr(arg, "strip")
                and hasattr(arg, "__getitem__")
                or hasattr(arg, "__iter__"))

    def _parse(self, lines):
        parsing_parameters = True
        indices = {}
        for line in lines:
            if _is_comment(line):
                continue
            if not line:
                parsing_parameters = False
                continue
            if parsing_parameters:
                self._parse_parameter(line)
            else:
                entry = self._parse_line(line)
                name = entry['name']
                if name in indices:
                    entry = self._merge_entries(entry, self.name_dictionaries[indices[name]])
                    entry['name'] = name
                    self.name_dictionaries[indices[name]] = entry
                else:
                    indices[name] = len(self.name_dictionaries)
                    self.name_dictionaries.append(entry)


    def _merge_entries(self, one, two):
        merged = {}
        for key in one:
            if key not in two:
                self._fatal("Expected key '%s' not found in entry: %s" % (key, two))
            if one[key] and two[key]:
                val_one = one[key]
                val_two = two[key]
                if isinstance(val_one, list) and isinstance(val_two, list):
                    val = val_one + val_two
                elif isinstance(val_one, list):
                    val = val_one + [val_two]
                elif isinstance(val_two, list):
                    val = [val_one] + val_two
                else:
                    val = [val_one, val_two]
                merged[key] = val
            elif one[key]:
                merged[key] = one[key]
            else:
                merged[key] = two[key]
        return merged


    def _parse_parameter(self, line):
        if '=' in line:
            name, value = line.split('=')
        else:
            name, value = line, True
        if not name in self.parameters:
            self._fatal("Unknown parameter: '%s' in line:\n%s\nKnown parameters: %s" % (name, line, self.parameters.keys()))
        self.parameters[name] = value

    def _parse_line(self, line):
        args = copy.deepcopy(self._defaults)
        parts = line.split(' ')
        args['name'] = parts[0]
        # re-join the rest of the line and split on ','
        args_list = ' '.join(parts[1:]).strip().split(',')
        for arg_string in args_list:
            arg_string = arg_string.strip()
            if not arg_string: # Ignore empty args
                continue
            if '=' in arg_string:
                arg_name, arg_value = arg_string.split('=')
            else:
                arg_name, arg_value = arg_string, True
            if arg_name not in self._defaults:
                self._fatal("Unknown argument: '%s' in line:\n%s\nKnown arguments: %s" % (arg_name, line, self._defaults.keys()))
            valid_values = self._valid_values.get(arg_name)
            if valid_values and arg_value not in valid_values:
                self._fatal("Unknown value: '%s' in line:\n%s\nKnown values: %s" % (arg_value, line, valid_values))
            if self._is_sequence(args[arg_name]):
                args[arg_name].append(arg_value)
            else:
                args[arg_name] = arg_value
        return args

    def _fatal(self, message):
        # FIXME: This should probably raise instead of exit(1)
        print message
        exit(1)
