#
# Copyright (C) 2019 Martin Owens
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
"""
Utilities functions for inkscape extension manager.
"""

import os
import sys

from collections import defaultdict
from email.parser import FeedParser
from appdirs import user_cache_dir

from inkex.inx import InxFile

CACHE_DIR = user_cache_dir('inkscape-extension-manager', 'Inkscape')
INKSCAPE_VERSION = os.environ.get('INKSCAPE_VERSION', None)
INKSCAPE_PROFILE = os.environ.get('INKSCAPE_PROFILE_DIR', None)

if not INKSCAPE_PROFILE and 'VIRTUAL_ENV' in os.environ:
    INKSCAPE_PROFILE = os.path.dirname(os.environ['VIRTUAL_ENV'])

if not INKSCAPE_PROFILE:
    sys.stderr.write("The Inkscape profile directory isn't set!\n")
    sys.exit(2)

DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
ICON_SEP = ('-' * 12) + 'SVGICON' + ('-' * 12)

def _pythonpath():
    for pth in os.environ.get('PYTHONPATH', '').split(':'):
        if os.path.isdir(pth):
            yield pth

def get_user_directory():
    """Return the user directory where extensions are stored."""
    if 'INKSCAPE_PROFILE_DIR' in os.environ:
        return os.path.abspath(
            os.path.expanduser(
                os.path.join(os.environ['INKSCAPE_PROFILE_DIR'], 'extensions')))

    home = os.path.expanduser("~")
    for pth in _pythonpath():
        if pth.startswith(home):
            return pth

def get_inkscape_directory():
    """Return the system directory where inkscape's core is."""
    for pth in _pythonpath():
        if os.path.isdir(os.path.join(pth, 'inkex')):
            return pth


def format_requires(string):
    """Get a version requires."""
    primary = string.split('; ', 1)[0]
    if '(' in primary:
        primary, version = primary.split('(', 1)
        return (primary.strip(), version.strip(') '))
    return (primary.strip(), None)

def parse_metadata(data):
    """
    Convert older email based meta data into a newer json format,
    See PEP 566 for details.
    """
    feed_parser = FeedParser()
    feed_parser.feed(data)
    metadata = feed_parser.close()

    def getdict():
        """Multi-dimentional dictionary"""
        return defaultdict(getdict)
    ret = defaultdict(getdict)

    ret['description'] = metadata.get_payload()
    ret['requires'] = [ format_requires(m)
        for m in metadata.get_all('Requires-Dist', [])
    ]

    for key, value in metadata.items():
        if key == 'Home-page':
            ret['extensions']['python.details']['project_urls']['Home'] = value
        elif key == 'Classifier':
            ret['classifiers'] = list(ret['classifiers'])
            ret['classifiers'].append(value)
        else:
            ret[key.lower().replace('-', '_')] = value

    return ret

def clean_author(data):
    """Clean the author so it has consistant keys"""
    for contact in data.get('extensions', {}).get('python.details', {}).get('contacts', []):
        if contact['role'] == 'author':
            data['author'] = contact['name']
            data['author_email'] = contact.get('email', '')
            if '<' in data['author']:
                data['author'], other = data['author'].split('<', 1)
                if '@' in other and not data['author_email']:
                    data['author_email'] = data['author'].split('>')[0]
    return data

class ExtensionInx(InxFile):
    """Information about an extension specifically"""
    ident = property(lambda self: super().ident or f"[no-id] {self.filename}")
    name = property(lambda self: super().name or f"[unnamed] {self.ident}")

    @property
    def menu(self):
        menu = self.xml.find_one('effect/effects-menu')
        if menu is not None and menu.get('hidden', "false") == "true":
            return ["_hidden", self.name]
        return super().menu
