# -*- coding: utf-8 -*-
# Copyright (c) 2016 Open Steno Project
# See LICENSE.txt for details.

"""Tests for misc.py."""

import inspect
import os
import sys

import pytest

import plover.misc as misc
import plover.oslayer.config as conf
from plover.resource import ASSET_SCHEME

from . import parametrize


def test_popcount_8():
    for n in range(256):
        assert misc.popcount_8(n) == format(n, 'b').count('1')
    with pytest.raises(AssertionError):
        misc.popcount_8(256)
    with pytest.raises(AssertionError):
        misc.popcount_8(-1)


if sys.platform.startswith('win32'):
    ABS_PATH = os.path.normcase(r'c:\foo\bar')
else:
    ABS_PATH = '/foo/bar'

@parametrize((
    # Asset, no change.
    lambda:
    (ASSET_SCHEME + 'foo:bar',
     ASSET_SCHEME + 'foo:bar'),
    # Absolute path, no change.
    lambda:
    (ABS_PATH,
     ABS_PATH),
    # Relative path, resolve relative to configuration directory.
    lambda:
    (os.path.normcase(os.path.normpath('foo/bar')),
     os.path.normcase(os.path.join(os.path.realpath(conf.CONFIG_DIR),
                                   'foo', 'bar'))),
    # Path below the user home directory.
    lambda:
    (os.path.normcase(os.path.normpath('~/foo/bar')),
     os.path.normcase(os.path.expanduser(os.path.normpath('~/foo/bar')))),
))
def test_dictionary_path(short_path, full_path):
    for input, function, expected in (
        # Unchanged.
        (short_path, 'shorten', short_path),
        (full_path, 'expand', full_path),
        # Shorten.
        (full_path, 'shorten', short_path),
        # Expand.
        (short_path, 'expand', full_path),
    ):
        function = '%s_path' % function
        result = getattr(misc, function)(input)
        assert result == expected, function

@parametrize((
    # Boolean.
    lambda: (False, False),
    lambda: (True, True),
    # True string values.
    lambda: ('1', True),
    lambda: ('yes', True),
    lambda: ('true', True),
    lambda: ('on', True),
    # False string values.
    lambda: ('0', False),
    lambda: ('no', False),
    lambda: ('false', False),
    lambda: ('off', False),
    # Invalid string values.
    lambda: ('yep', ValueError),
    lambda: ('nope', ValueError),
    # Other types.
    lambda: (0, False),
    lambda: (1, True),
    lambda: (42, True),
    lambda: (4.2, True),
    lambda: (0.0, False),
    lambda: (None, False),
))
def test_boolean(input, output):
    if inspect.isclass(output):
        with pytest.raises(output):
            misc.boolean(input)
    else:
        assert misc.boolean(input) == output

def test_to_surrogate_pairs():
    # Split unicode characters above 0xFFFF
    assert misc.to_surrogate_pair(chr(0x1F4A6)) == [0xD83D, 0xDCA6]
    # Do not slit characters below 0xFFFF
    assert misc.to_surrogate_pair(chr(0x20)) == [0x20]
    # Do not split already split characters.
    assert misc.to_surrogate_pair(chr(0xD83D) + chr(0xDCA6)) == [0xD83D, 0xDCA6]
