import logging
import json
import jsonref
import os.path
import sys
from subprocess import call
from os import listdir
from os.path import isfile, join
import pathlib
from .exceptions import *
logger = logging.getLogger()

def format_file_with_clang(outfile):
    if sys.platform.startswith("win"):
        call([r"C:\Program Files\LLVM\bin\clang-format.exe", "-i", "-verbose", "-style=file", outfile])
    elif sys.platform.startswith("linux"):
        call([r"clang-format", "-i", "-verbose", "-style=file", outfile])


def write_file(file_name, text, out_dir, mode='w'):
    abs_file_path = os.path.join(out_dir, file_name)
    f = open(abs_file_path, mode)
    f.write(text)
    f.close()
    format_file_with_clang(abs_file_path)


def load_json_schema(filename, allow_deref=False, my_dir=None):
    """
    load the JSON schema file
    :param filename: filename (with extension)
    :param my_dir: path to the file
    :return: json_dict
    """
    logger.debug("load_json_schema: Load %s file from schema dir %s", filename, my_dir)

    full_path = filename
    if my_dir is not None:
        full_path = os.path.join(my_dir, filename)
    else:
        raise SwaggerInputError("schema_dir", "Schema dir is not accessible/present")

    if os.path.isfile(full_path) is False:
        logger.debug("%s json file does not exist", full_path)
        raise SwaggerInputError(full_path, "Json file does not exists")

    logger.debug("load_json_schema: Full path %s", full_path)

    linestring = open(full_path, 'r').read()
    json_dict = json.loads(linestring)
    json_ref_dict = None

    if allow_deref:
        schema_path = os.path.abspath(os.path.dirname(full_path))
        base_uri = pathlib.Path(schema_path).as_uri()
        base_uri += '/'
        logger.debug("load_json_schema: Base URI for json deref %s", base_uri)
        json_ref_dict = jsonref.load(open(full_path, 'r'), base_uri=base_uri, jsonschema=True)

    if allow_deref:
        return json_ref_dict, json_dict
    else:
        return json_dict


def get_dir_list(dir, ext=None):
    """
    get all files (none recursive) in the specified dir
    :param dir: path to the directory
    :param ext: filter on extension
    :return: list of files (only base_name)
    """
    only_files = [f for f in listdir(dir) if isfile(join(dir, f))]
    # remove .bak files
    new_list = [x for x in only_files if not x.endswith(".swp")]
    if ext is not None:
        cur_list = new_list
        new_list = [x for x in cur_list if x.endswith(ext)]
    return new_list


def strip_name_convention(text):
    if text.startswith('qti.allplay.r.'):
        return strip_left(text, 'qti.allplay.r.')
    return strip_left(text, 'qti.iotsys.r.')


def strip_right(str, suffix):
    text = str.lower()
    if not text.endswith(suffix.lower()):
        return str
    # else
    return str[:len(text)-len(suffix.lower())]


def strip_left(str, prefix):
    text = str.lower()
    if not text.startswith(prefix.lower()):
        return str
    # else
    return str[len(prefix.lower()):]


def dict_find_item(obj, key):
    if key in obj: return obj[key]
    for k, v in obj.items():
        if isinstance(v, dict):
            item = dict_find_item(v, key)
            if item is not None:
                return item


def remove_list_duplicates(seq):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if not (x in seen or seen_add(x))]
