#
# Copyright (C) 2016 The Android Open Source ProjectSpec
#
# 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.

"""
  This file defines the project Config class.
"""

import os


from project import common


class Config(object):
    """Config represents project-specific runtime configuration.

    When a given Project is being built, the supporting tools
    will have configuration that relates more to the host environment
    and less to the creating project artifacts.  These may be
    output and cache directories or the defaults for commandline
    tool behavior.
    """
    def __init__(self, base_path=os.getcwd()):
        self._version = 1
        self._cache_dir = 'bdk.cache'
        self._output_dir = 'bdk.out'
        # Fake up an origin using the current directory or a passed
        # in base path.
        self._origin = common.Origin()
        self._origin.source_file = os.path.join(base_path, 'placeholder')
        self._default_target = ''

    def _abs_dir(self, p):
        if os.path.isabs(p):
            return p
        # Automatically absolutize relative paths against the origin.
        return os.path.join(os.path.dirname(self._origin.source_file), p)

    @property
    def cache_dir(self):
        """Returns the absolute path dir."""
        return self._abs_dir(self._cache_dir)

    @cache_dir.setter
    def cache_dir(self, path):
        self._cache_dir = path

    @property
    def output_dir(self):
        """Returns the absolute path dir."""
        return self._abs_dir(self._output_dir)

    @output_dir.setter
    def output_dir(self, path):
        self._output_dir = path

    @property
    def default_target(self):
        return self._default_target

    @default_target.setter
    def default_target(self, target_name):
        self._default_target = target_name

    @property
    def origin(self):
        return self._origin

    @origin.setter
    def origin(self, o):
        self._origin = o.copy()

    def __repr__(self):
        return ('<config>'
                '<output-dir path="{}"/>'
                '<cache-dir path="{}"/>'
                '<default target="{}"/></config>').format(
                    self._output_dir, self._cache_dir, self._default_target)

    def cache_path_for_target(self, target, *path):
        return os.path.join(self.cache_dir, '{}.cache'.format(target.name),
                            *path)

    def artifact_cache_for_target(self, target):
        return self.cache_path_for_target(target, 'build_root')

    def metadata_cache_for_target(self, target):
        return self.cache_path_for_target(target, 'metadata')

    @classmethod
    def from_element(cls, node):
        """Creates a new Config from the @node.

        Args:
            node: The ElementTree node a <config> element.

        Returns:
            instance of Config

        Raises:
            common.LoadErrorWithOrigin
        """
        config = cls()
        config.origin = node.origin
        node.limit_attribs([])
        # Ensure we have a project document.
        if node.tag != 'config':
            raise common.LoadErrorWithOrigin(node.origin, 'node not <config>')

        # Parse the dirs
        for tag in ('output-dir', 'cache-dir'):
            for ele in node.findall(tag):
                ele.limit_attribs(['path'])
                if 'path' in ele.attrib:
                    config.__dict__['_' + tag.replace('-', '_')] = (
                        ele.get_attrib('path'))

        # Grab the default element.
        for ele in node.findall('default'):
            ele.limit_attribs(['target'])
            if 'target' in ele.attrib:
                config.default_target = ele.get_attrib('target')

        return config
