# Copyright 2020 The Pigweed Authors
#
# 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
#
#     https://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.
"""Test API for enviroment."""

from __future__ import annotations

import re

from PB.recipe_modules.pigweed.environment import options as env_options
from recipe_engine import recipe_test_api


class EnvironmentTestApi(recipe_test_api.RecipeTestApi):
    """Test API for Enviroment."""

    def properties(
        self,
        *,
        name='environment_options',
        config_file='config_file.json',
        relative_pigweed_root='pigweed',
        skip_submodule_check=False,
        additional_variables=None,
        additional_cipd_files=None,
        allow_doctor_to_fail=False,
    ):
        opts = env_options.Options()
        opts.config_file = config_file
        opts.relative_pigweed_root = relative_pigweed_root
        opts.skip_submodule_check = skip_submodule_check
        for key, value in (additional_variables or {}).items():
            opts.additional_variables[key] = str(value)
        opts.additional_cipd_files.extend(additional_cipd_files or ())
        opts.allow_doctor_to_fail = allow_doctor_to_fail

        return self.m.properties(**{name: opts})

    def override_clang(self, cas_digest=None, cipd_version=None):
        assert bool(cas_digest) != bool(
            cipd_version
        ), 'exactly one of cas_digest or cipd_version is required'
        tc = {}
        if cas_digest:
            tc['cas_digest'] = cas_digest
        if cipd_version:
            tc['cipd_version'] = cipd_version

        props = {
            '$fuchsia/checkout': {'clang_toolchain': tc},
        }

        return self.m.properties(**props)
