from typing import Any, List, Dict, Optional, Union, Set
from urllib.parse import urlsplit, urlunsplit
from pathlib import Path
import importlib.util
import importlib
import logging
import os
import re
import aioredis
from aioredis.commands import Redis
import cowsay


async def get_redis_conn() -> Redis:
    """Connect to Redis server with environment variable REDIS_ADDR and optional environment variable REDIS_PASS."""
    address = os.environ.get('REDIS_ADDR')
    if address is None:
        address = 'redis://localhost/0'
        logging.warning(
            f"Environment variable REDIS_ADDR is not set! Using default address: {address}")
    conn = await aioredis.create_redis(address, password=os.environ.get('REDIS_PASS'))
    if not conn.closed:
        return conn
    logging.error(f"Could establish connection to Redis at {address}!")


def import_module(module_path: str) -> 'module':
    """Dynamically import a module from a file path or module name."""
    # file path has '/' separator. module path has '.' seperator.
    if '/' in module_path:
        # import module from .py file
        module_spec = importlib.util.spec_from_file_location(
            Path(module_path).stem, module_path)
        module = importlib.util.module_from_spec(module_spec)
        try:
            module_spec.loader.exec_module(module)
            return module
        except FileNotFoundError:
            logging.error(cowsay.daemon(f"Module not found: {module}"))
    else:
        # import module from module path.
        try:
            return importlib.import_module(module_path)
        except ImportError:
            logging.error(cowsay.daemon(
                f"Could not import module {module_path}!"))


def absolute_url(page_url: str, extracted_url: str) -> str:
    """Convert extracted_url to an absolute URL if it is a relative URL."""
    ext_url = urlsplit(extracted_url)
    if ext_url.scheme == "" or ext_url.netloc == "":
        pg_url = urlsplit(page_url)
        extracted_url = urlunsplit(
            (pg_url.scheme, pg_url.netloc, ext_url.path, ext_url.query, ext_url.fragment))
    return extracted_url


def extract_all_urls(html: str) -> Set[str]:
    extracted_urls = set([match.group(1)
                          for match in re.finditer(r'<a[^<>]+?href=([\'\"])(.*?)\1', html)])
