#
# Copyright (C) 2016 The Android Open Source Project
#
# 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 provides all Target element related parsing."""


from project import common
from project import platform


class Error(common.LoadErrorWithOrigin):
    """General Error for targets."""


class TargetLoadError(Error):
    """Raised when there is a problem loading a target."""
    description = 'Failed to load target'


class Target(object):
    """A target for a project.

    Specifies what a target consists of, and what platform
    it is intended for.
    """

    def __init__(self, name):
        self._name = name
        self._pack = None
        self._pack_name = ''
        self._origin = common.Origin()
        self._platform = None

    def __repr__(self):
        return ('<target name="{}" os="{}" os-version="{}" '
                'board="{}" board-version="{}" build="{}" pack="{}"/>').format(
                    self._name, self.platform.os.name, self.platform.os.version,
                    self.platform.device.name, self.platform.device.version,
                    self.platform.build_type, self._pack_name)

    @property
    def name(self):
        return self._name

    @property
    def platform(self):
        return self._platform

    @property
    def pack_name(self):
        return self._pack_name

    @property
    def pack(self):
        return self._pack

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

    def load(self, ele):
        """Populates this instance from Element @ele."""
        self._origin = ele.origin.copy()
        ele.limit_attribs(['name', 'pack', 'os', 'board',
                           'os-version', 'board-version', 'build'])
        self._pack_name = ele.get_attrib('pack')

        # Platform.
        build_type = 'userdebug'
        if 'build' in ele.attrib:
            build_type = ele.get_attrib('build')
        try:
            self._platform = platform.Platform(
                os_name=ele.get_attrib('os'),
                os_version=ele.get_attrib('os-version'),
                board=ele.get_attrib('board'),
                board_version=ele.get_attrib('board-version'),
                build_type=build_type)
        except platform.Error as e:
            raise TargetLoadError(self._origin, e)

    def create_submap(self, global_packmap):
        """Create a packmap from the global packmap.

        Prior to calling, populate the global packmap with any
        requires OS or Board packs.

        Args:
            global_packmap: A packmap of all available packs.

        Returns:
            A submap of global_packmap for this target, with paths validated.
        """
        aliases = {'os': self.platform.os_namespace,
                   'board': self.platform.board_namespace}
        packmap = global_packmap.submap(self._pack_name, aliases)
        packmap.check_paths()
        return packmap
