#!/usr/bin/env python3

import datetime
import getpass
import logging
import os
import platform
import sys

from typing import Any

import uno
from com.sun.star.beans import PropertyValue


__all__ = [
    'DESKTOP',
    'INFO_DEBUG',
    'IS_MAC',
    'IS_WIN',
    'LANG',
    'LANGUAGE',
    'NAME',
    'OS',
    'PC',
    'USER',
    'VERSION',
    'create_instance',
    'get_app_config',
    ]


CTX = uno.getComponentContext()
SM = CTX.getServiceManager()


# Global variables
OS = platform.system()
DESKTOP = os.environ.get('DESKTOP_SESSION', '')
PC = platform.node()
USER = getpass.getuser()
IS_WIN = OS == 'Windows'
IS_MAC = OS == 'Darwin'


LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
LOG_DATE = '%d/%m/%Y %H:%M:%S'
if IS_WIN:
    logging.addLevelName(logging.ERROR, 'ERROR')
    logging.addLevelName(logging.DEBUG, 'DEBUG')
    logging.addLevelName(logging.INFO, 'INFO')
else:
    logging.addLevelName(logging.ERROR, '\033[1;41mERROR\033[1;0m')
    logging.addLevelName(logging.DEBUG, '\x1b[33mDEBUG\033[1;0m')
    logging.addLevelName(logging.INFO, '\x1b[32mINFO\033[1;0m')
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE)
log = logging.getLogger(__name__)


def create_instance(name: str, with_context: bool=False, arguments: Any=None) -> Any:
    """Create a service instance

    :param name: Name of service
    :type name: str
    :param with_context: If used context
    :type with_context: bool
    :param argument: If needed some argument
    :type argument: Any
    :return: PyUno instance
    :rtype: PyUno Object
    """

    if with_context:
        instance = SM.createInstanceWithContext(name, CTX)
    elif arguments:
        instance = SM.createInstanceWithArguments(name, (arguments,))
    else:
        instance = SM.createInstance(name)

    return instance


def get_app_config(node_name: str, key: str='') -> Any:
    """Get any key from any node from LibreOffice configuration.

    :param node_name: Name of node
    :type name: str
    :param key: Name of key
    :type key: str
    :return: Any value
    :rtype: Any

    `See Api ConfigurationProvider <https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1configuration_1_1ConfigurationProvider.html>`_
    """

    name = 'com.sun.star.configuration.ConfigurationProvider'
    service = 'com.sun.star.configuration.ConfigurationAccess'
    cp = create_instance(name, True)
    node = PropertyValue(Name='nodepath', Value=node_name)
    value = ''

    try:
        value = cp.createInstanceWithArguments(service, (node,))
        if value and value.hasByName(key):
            value = value.getPropertyValue(key)
    except Exception as e:
        log.error(e)
        value = ''

    return value


# Get info LibO
NAME = TITLE = get_app_config('/org.openoffice.Setup/Product', 'ooName')
VERSION = get_app_config('/org.openoffice.Setup/Product','ooSetupVersion')
LANGUAGE = get_app_config('/org.openoffice.Setup/L10N/', 'ooLocale')
LANG = LANGUAGE.split('-')[0]

# Get start date from Calc configuration
node = '/org.openoffice.Office.Calc/Calculate/Other/Date'
year = get_app_config(node, 'YY')
month = get_app_config(node, 'MM')
day = get_app_config(node, 'DD')
DATE_OFFSET = datetime.date(year, month, day).toordinal()

_info_debug = f"Python: {sys.version}\n\n{platform.platform()}\n\n" + '\n'.join(sys.path)
INFO_DEBUG = f"{NAME} v{VERSION} {LANGUAGE}\n\n{_info_debug}"


def dict_to_property(values: dict, uno_any: bool=False):
    """Convert dictionary to array of PropertyValue

    :param values: Dictionary of values
    :type values: dict
    :param uno_any: If return like array uno.Any
    :type uno_any: bool
    :return: Tuple of PropertyValue or array uno.Any
    :rtype: tuples or uno.Any
    """
    ps = tuple([PropertyValue(Name=n, Value=v) for n, v in values.items()])
    if uno_any:
        ps = uno.Any('[]com.sun.star.beans.PropertyValue', ps)
    return ps


class BaseObject():

    def __init__(self, obj):
        self._obj = obj

    def __enter__(self):
        return self

    @property
    def obj(self):
        """Return original pyUno object"""
        return self._obj

