# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-

import ctypes
import traceback
import os
from ctypes import *

import user_data.settings
import toxygen_wrapper.tox
import toxygen_wrapper.toxcore_enums_and_consts as enums
from toxygen_wrapper.tests import support_testing as ts
# callbacks can be called in any thread so were being careful
# tox.py can be called by callbacks
from toxygen_wrapper.tests.support_testing import LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG, LOG_TRACE

global LOG
import logging
LOG = logging.getLogger('app.'+'tox_factory')

from utils import util
from utils import ui as util_ui


def tox_factory(data=None, settings=None, args=None, app=None):
    """
    :param data: user data from .tox file. None = no saved data, create new profile
    :param settings: current profile settings. None = default settings will be used
    :return: new tox instance
    """
    if not settings:
        LOG_WARN("tox_factory using get_default_settings")
        settings = user_data.settings.Settings.get_default_settings()
    else:
        user_data.settings.clean_settings(settings)

    try:
        tox_options = toxygen_wrapper.tox.Tox.options_new()
        tox_options.contents.ipv6_enabled = settings['ipv6_enabled']
        tox_options.contents.udp_enabled = settings['udp_enabled']
        tox_options.contents.proxy_type = int(settings['proxy_type'])
        if type(settings['proxy_host']) == str:
            tox_options.contents.proxy_host = bytes(settings['proxy_host'],'UTF-8')
        elif type(settings['proxy_host']) == bytes:
            tox_options.contents.proxy_host = settings['proxy_host']
        else:
            tox_options.contents.proxy_host = b''
        tox_options.contents.proxy_port = int(settings['proxy_port'])
        tox_options.contents.start_port = settings['start_port']
        tox_options.contents.end_port = settings['end_port']
        tox_options.contents.tcp_port = settings['tcp_port']
        tox_options.contents.local_discovery_enabled = settings['local_discovery_enabled']
        tox_options.contents.dht_announcements_enabled = settings['dht_announcements_enabled']
        tox_options.contents.hole_punching_enabled = settings['hole_punching_enabled']
        if data:  # load existing profile
            tox_options.contents.savedata_type = enums.TOX_SAVEDATA_TYPE['TOX_SAVE']
            tox_options.contents.savedata_data = ctypes.c_char_p(data)
            tox_options.contents.savedata_length = len(data)
        else:  # create new profile
            tox_options.contents.savedata_type = enums.TOX_SAVEDATA_TYPE['NONE']
            tox_options.contents.savedata_data = None
            tox_options.contents.savedata_length = 0

        # overrides
        tox_options.contents.local_discovery_enabled = False
        tox_options.contents.ipv6_enabled = False
        tox_options.contents.hole_punching_enabled = False

        LOG.debug("toxygen_wrapper.tox.Tox settings: " +repr(settings))

        if 'trace_enabled' in settings and not settings['trace_enabled']:
            LOG_DEBUG("settings['trace_enabled' disabled" )
        elif tox_options._options_pointer and \
          'trace_enabled' in settings and settings['trace_enabled']:
            ts.vAddLoggerCallback(tox_options)
            LOG_INFO("c-toxcore trace_enabled enabled" )
        else:
            LOG_WARN("No tox_options._options_pointer to add self_logger_cb" )

        retval = toxygen_wrapper.tox.Tox(tox_options)
    except Exception as e:
        if app and hasattr(app, '_log'):
            pass
        LOG_ERROR(f"toxygen_wrapper.tox.Tox failed:  {e}")
        LOG_WARN(traceback.format_exc())
        raise

    if app and hasattr(app, '_log'):
        app._log("DEBUG: toxygen_wrapper.tox.Tox succeeded")
    return retval
