from ctags import CTags, TagEntry
import sys
from os import listdir, path
from . import config


def getAllFiles():
    files = [f for f in listdir(
        config.files_folder) if '.wiki' in f and path.isfile(config.files_folder + f)]
    files = set(files)
    return files


def loadTagFile(path=config.files_folder + '.vimwiki_tags'):
    # Available file information keys:
    #  opened -  was the tag file successfully opened?
    #  error_number - errno value when 'opened' is false
    #  format - format of tag file (1 = original, 2 = extended)
    #  sort - how is the tag file sorted?
    #  author - name of author of generating program (may be empy string)
    #  name - name of program (may be empy string)
    #  url - URL of distribution (may be empy string)
    #  version - program version (may be empty string)
    try:
        tagFile = CTags(path)
        return tagFile
    except:
        print("No tagfile at {}".format(path))
        sys.exit(1)


def makeSetFromTags(tagFile, key='file'):
    # Available TagEntry keys:
    #  name - name of tag
    #  file - path of source file containing definition of tag
    #  pattern - pattern for locating source line (None if no pattern)
    #  lineNumber - line number in source file of tag definition (may be zero if not known)
    #  kind - kind of tag (none if not known)
    #  fileScope - is tag of file-limited scope?

    # Note: other keys will be assumed as an extension key and will
    # return None if no such key is found
    entry = TagEntry()
    tag = tagFile.next(entry)
    AllFileList = set()
    while tag:
        AllFileList.add(entry[key].decode())
        tag = tagFile.next(entry)
    return AllFileList


def makeDictFromTags(tagFile, key='name', value='file'):
    entry = TagEntry()
    tag = tagFile.next(entry)
    allFiles = getAllFiles()
    ret = {}
    while tag:
        # Not sure why they're being read as bytes now?
        strKey = entry[key].decode()
        strValue = entry[value].decode()
        if strValue in allFiles:
            if strKey not in ret.keys():
                ret[strKey] = set()
                ret[strKey].add(strValue)
            else:
                ret[strKey].add(strValue)
        else:
            print(f"found only tag {strValue}")
        tag = tagFile.next(entry)
    return ret


def getAllFilesWithTags():
    # Returns a set containing all the files we wish to make public
    ret = makeSetFromTags(loadTagFile())
    allFiles = getAllFiles()
    onlyTags = ret - allFiles
    return ret - onlyTags


def getUntaggedFiles():
    allFiles = getAllFiles()
    allTags = getAllFilesWithTags()
    return allFiles - allTags


def getAllTags():
    # Returns a dictionary with:
    # - key as tag titles
    # - values as files that have the key in their tags
    all_tags = makeDictFromTags(loadTagFile())
    print(f"untagged: {getUntaggedFiles()}")
    all_tags['untagged'] = getUntaggedFiles()
    return all_tags
