from __future__ import print_function
import sys
import time
import re
import json
import typing

ERROR_DURING_OPERATION = -1
EXIT_FAILURE = 1
EXIT_SUCCESS = 0


def get_timestamp() -> str:
    return time.strftime('%Y-%m-%d %H-%M-%S')


def log_out(*args, file=sys.stdout, **kwargs) -> None:
    print("[+] ", file=file, end='')
    print(*args, file=file, **kwargs)


def log_warn(*args, file=sys.stderr, **kwargs) -> None:
    print("[!] ", file=file, end='')
    print(*args, file=file, **kwargs)


def log_err(*args, file=sys.stderr, **kwargs) -> None:
    print("[!] ", file=file, end='')
    print(*args, file=file, **kwargs)


def read_configuration(filename=r"./volume/conf.json") -> dict:
    try:
        with open(filename, 'r') as f:
            try:
                return json.loads(f.read())
            except json.JSONDecodeError as error:
                log_err(
                    f"Reading {filename} generated:\n{str(error)}")
                exit_failure_settings()
    except FileNotFoundError as error:
        log_err(f"Opening  {filename} generated:\n{str(error)}")
        exit_failure_settings()


def check(checker_function: typing.Callable[[typing.Any], typing.Any],
          to_check: typing.Any, settings_field: str):
    log_out(f"Checking {settings_field} field...")
    ret = checker_function(to_check)
    log_out(f"{settings_field} checked!\n")
    return ret


def check_ips(d: list) -> list:
    opponents = []
    regex = r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])" \
            r"\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
    pattern = re.compile(regex)

    for opp in d:
        if pattern.match(opp):
            opponents.append(opp)
        else:
            log_err(f"{opp} is not a valid IP address")
            exit_failure_settings()

    return opponents


def check_integer_from_str(s: str) -> int:
    try:
        return int(s)
    except ValueError as e:
        log_err(f"{s} is not a valid integer:\n{e}")
        exit_failure_settings()


def check_url(s: str) -> str:
    regex = r"((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+" \
            r"|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\_w-]*)" \
            r"?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)"
    pattern = re.compile(regex)
    if pattern.match(s):
        return s
    else:
        log_err(f"{s} is not a valid URL")
        exit_failure_settings()


def check_regex(s: str) -> str:
    try:
        re.compile(s)
        return s
    except re.error:
        log_err(f"{s} is not a valid regex")
        exit_failure_settings()


def check_protocol(s: str) -> str:
    p = s.upper()
    if p in ["GET", "POST", "TCP", "CUSTOM", "CUSTOM-QUEUED"]:
        return p
    else:
        log_err(f"{s} is not a valid protocol")
        exit_failure_settings()


def exit_success() -> None:
    sys.exit(EXIT_SUCCESS)


def exit_failure() -> None:
    sys.exit(EXIT_FAILURE)


def exit_success_settings() -> None:
    exit_success()  # TODO


def exit_failure_settings() -> None:
    exit_failure()  # TODO


def exit_success_attacker() -> None:
    exit_success()  # TODO


def exit_failure_attacker() -> None:
    exit_failure()  # TODO
