# Copyright 2017, 2019 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from . import ExtensionModule

from .. import mesonlib
from ..mesonlib import typeslistify
from ..interpreterbase import FeatureNew, noKwargs, InvalidCode

import os

class KeyvalModule(ExtensionModule):

    @FeatureNew('Keyval Module', '0.55.0')
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.snippets.add('load')

    def _load_file(self, path_to_config):
        result = dict()
        try:
            with open(path_to_config) as f:
                for line in f:
                    if '#' in line:
                        comment_idx = line.index('#')
                        line = line[:comment_idx]
                    line = line.strip()
                    try:
                        name, val = line.split('=', 1)
                    except ValueError:
                        continue
                    result[name.strip()] = val.strip()
        except OSError as e:
            raise mesonlib.MesonException(f'Failed to load {path_to_config}: {e}')

        return result

    @noKwargs
    def load(self, interpreter, state, args, kwargs):
        sources = typeslistify(args, (str, mesonlib.File))
        if len(sources) != 1:
            raise InvalidCode('load takes only one file input.')

        s = sources[0]
        is_built = False
        if isinstance(s, mesonlib.File):
            is_built = is_built or s.is_built
            s = s.absolute_path(interpreter.environment.source_dir, interpreter.environment.build_dir)
        else:
            s = os.path.join(interpreter.environment.source_dir, s)

        if s not in interpreter.build_def_files and not is_built:
            interpreter.build_def_files.append(s)

        return self._load_file(s)


def initialize(*args, **kwargs):
    return KeyvalModule(*args, **kwargs)
