# All Rights Reserved.
#
#    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.

import os
import typing as t

import requests

from rally import exceptions
from rally.common.plugin import plugin
from rally.task import types


@plugin.configure(name="path_or_url")
class PathOrUrl(types.ResourceType):
    """Check whether file exists or url available."""

    def pre_process(
        self,
        *,
        resource_spec: str,
        config: types.ConvertConfig,
        output_type: t.Any,
    ) -> str:
        path = os.path.expanduser(resource_spec)
        if os.path.isfile(path):
            return path
        try:
            head = requests.head(path, verify=False, allow_redirects=True)
            if head.status_code == 200:
                return path
            raise exceptions.InvalidScenarioArgument(
                f"Url {path} unavailable (code {head.status_code})"
            )
        except Exception as ex:
            raise exceptions.InvalidScenarioArgument(
                f"Url error {path} ({ex})"
            )


@plugin.configure(name="file")
class FileType(types.ResourceType):
    """Return content of the file by its path."""

    def pre_process(
        self,
        *,
        resource_spec: str,
        config: types.ConvertConfig,
        output_type: t.Any,
    ) -> str:
        with open(os.path.expanduser(resource_spec)) as f:
            return f.read()


@plugin.configure(name="expand_user_path")
class ExpandUserPath(types.ResourceType):
    """Expands user path."""

    def pre_process(
        self,
        *,
        resource_spec: str,
        config: types.ConvertConfig,
        output_type: t.Any,
    ) -> str:
        return os.path.expanduser(resource_spec)


@plugin.configure(name="file_dict")
class FileTypeDict(types.ResourceType):
    """Return the dictionary of items with file path and file content."""

    def pre_process(
        self,
        *,
        resource_spec: list[str],
        config: types.ConvertConfig,
        output_type: t.Any,
    ) -> dict[str, str]:
        file_type_dict: dict[str, str] = {}
        for file_path in resource_spec:
            file_path = os.path.expanduser(file_path)
            with open(file_path) as f:
                file_type_dict[file_path] = f.read()

        return file_type_dict
