# -*- coding: utf-8 -*-

"""Mocks for PyBEL testing."""

import itertools as itt
import os
from unittest import mock

from .constants import bel_dir_path, belanno_dir_path, belns_dir_path
from .utils import get_uri_name

__all__ = [
    "MockResponse",
    "MockSession",
    "mock_bel_resources",
]

_responses = [
    ("go.belns", os.path.join(belns_dir_path, "go-names.belns")),
    (
        "hgnc-human-genes-20170725.belns",
        os.path.join(belns_dir_path, "hgnc-names.belns"),
    ),
    ("chebi-20170725.belns", os.path.join(belns_dir_path, "chebi-names.belns")),
    (
        "species-taxonomy-id-20170511.belanno",
        os.path.join(belanno_dir_path, "species-taxonomy-id.belanno"),
    ),
    (
        "confidence-1.0.0.belanno",
        os.path.join(belanno_dir_path, "confidence-1.0.0.belanno"),
    ),
]


class MockResponse:
    """See http://stackoverflow.com/questions/15753390/python-mock-requests-and-the-response."""

    def __init__(self, url_to_mock: str):
        """Build a mock for the requests Response object."""
        _r = [
            (".belns", os.path.join(belns_dir_path, get_uri_name(url_to_mock))),
            (".belanno", os.path.join(belanno_dir_path, get_uri_name(url_to_mock))),
            (".bel", os.path.join(bel_dir_path, get_uri_name(url_to_mock))),
        ]

        self.path = None
        for suffix, path in itt.chain(_responses, _r):
            if url_to_mock.endswith(suffix):
                self.path = path
                break

        if self.path is None:
            raise ValueError("missing file")

        if not os.path.exists(self.path):
            raise ValueError("file doesn't exist: {}".format(self.path))

    def iter_lines(self):
        """Iterate the lines of the mock file."""
        with open(self.path, "rb") as file:
            yield from file

    def raise_for_status(self):
        """Mock raising an error, by not doing anything at all."""


class MockSession:
    """Patches the session object so requests can be redirected through the filesystem without rewriting BEL files."""

    def mount(self, prefix, adapter):
        """Mock mounting an adapter by not doing anything."""

    @staticmethod
    def get(url: str):
        """Mock getting a URL by returning a mock response."""
        return MockResponse(url)

    def close(self):
        """Mock closing a connection by not doing anything."""


mock_bel_resources = mock.patch("bel_resources.utils.requests.Session", side_effect=MockSession)
