import os
from pathlib import Path
import re
from typing import List
import platform
import sys
import traceback
from io import FileIO

def exit_with_err(err: Exception, logfile: FileIO=None):
    """
    Exit the current step and display the err.
    :param: err, the error/exception encountered.
    """
    if logfile:
        traceback.print_exc(file=logfile)
    else:
        traceback.print_exc()
    sys.exit(1)


def set_env_var(key: str, value: str, delimiter: str='~'):
    """
    Set the GitHub env variable of 'key' to 'value' using
    the method specified here:
    https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
    Support both Windows and Ubuntu machines provided by GitHub Actions.

    :param: key, the name of the env variable.
    :param: value, the value of the env variable.
    :param: delimiter, the delimiter that you want to use
    to write to the file. Only applicable if the 'value' contains
    '\n' character aka a multiline string.
    """
    if platform.system() == "Windows":
        if "\n" in value:
            os.system(f'echo "{key}<<{delimiter}" >> %GITHUB_ENV%')
            os.system(f'echo "{value}" >> %GITHUB_ENV%')
            os.system(f'echo "{delimiter}" >> %GITHUB_ENV%')
        else:
            os.system(f'echo "{key}={value}" >> %GITHUB_ENV%')
    elif platform.system() == "Linux":
        if "\n" in value:
            os.system(f'echo "{key}<<{delimiter}" >> $GITHUB_ENV')
            os.system(f'echo "{value}" >> $GITHUB_ENV')
            os.system(f'echo "{delimiter}" >> $GITHUB_ENV')
        else:
            os.system(f'echo "{key}={value}" >> $GITHUB_ENV')
    else:
        raise Exception("This function doesn't support this platform: " + platform.system())


def find_object_added_in_pr(icons: List[dict], pr_title: str):
    """
    Find the icon name from the PR title. 
    :param icons, a list of the font objects found in the devicon.json.
    :pr_title, the title of the PR that this workflow was called on.
    :return a dictionary with the "name"
    entry's value matching the name in the pr_title.
    :raise If no object can be found, raise an Exception.
    """
    try:
        pattern = re.compile(r"(?<=^new icon: )\w+ (?=\(.+\))|(?<=^update icon: )\w+ (?=\(.+\))", re.I)
        icon_name_index = 0
        icon_name = pattern.findall(pr_title)[icon_name_index].lower().strip()  # should only have one match
        icon = [icon for icon in icons if icon["name"] == icon_name][0]
        return icon
    except IndexError as e:  # there are no match in the findall()
        print(e)
        message = "util.find_object_added_in_pr: Couldn't find an icon matching the name in the PR title.\n" \
            f"PR title is: '{pr_title}'"
        raise Exception(message)


def is_svg_in_font_attribute(svg_file_path: Path, devicon_object: dict): 
    """
    Check if svg is in devicon.json's font attribute.
    :param svg_file_path, the path to a single svg icon
    :devicon_object, an object for a single icon inside devicon.json
    :return true if the svg exists in the devicon_object's font attribute, false if it doesn't
    """
    icon_version = Path(svg_file_path).stem.split('-', 1)[1]
    font_object = devicon_object["versions"]["font"]
    return icon_version in font_object


valid_svg_filename_pattern = re.compile(r"-(original|plain|line)(-wordmark)?\.svg$")
def is_svg_name_valid(filename: str):
    return valid_svg_filename_pattern.search(filename) is not None


valid_svg_version_pattern = re.compile(r"^(original|plain|line)(-wordmark)?$")
def is_svg_version_valid(version):
    return valid_svg_version_pattern.search(version) is not None
