import pytest
import multiprocessing
import time
import os

from pymasep.app import App
from test.unit.mocks.interface_mock import InterfaceMock


def _thread_server_func(q, base_dir):
    try:
        app_server = App(InterfaceMock,
                         root_path=base_dir,
                         config_path=os.path.join(base_dir, 'integration/config', 'game_two_agents'),
                         launch=App.LAUNCH_SERVER_STANDALONE)
        app_server.run()
    except Exception as e:
        q.put(e)


def _thread_client_func(q, base_dir):
    try:
        app_interface = App(InterfaceMock,
                            root_path=base_dir,
                            config_path=os.path.join(base_dir, 'integration/config', 'game_two_agents'),
                            launch=App.LAUNCH_INTERFACE,
                            remote_engine_host='localhost', remote_engine_port=60000)
        app_interface.run()
    except Exception as e:
        q.put(e)


def _thread_client_search_remote_func(q, base_dir):
    try:
        app_interface = App(InterfaceMock,
                            root_path=base_dir,
                            config_path=os.path.join(base_dir, 'integration/config', 'game_two_agents'),
                            launch=App.LAUNCH_INTERFACE)
        app_interface.run()
    except Exception as e:
        q.put(e)


def _server_func(q, base_dir):
    try:
        app_server = App(InterfaceMock,
                         root_path=base_dir,
                         config_path=os.path.join(base_dir, 'integration/config', 'game_three_agents'),
                         launch=App.LAUNCH_ALL_LOCAL)
        app_server.run()
    except Exception as e:
        q.put(e)


def _client_func(q, base_dir):
    try:
        app_interface = App(InterfaceMock,
                            root_path=base_dir,
                            config_path=os.path.join(base_dir, 'integration/config', 'game_three_agents'),
                            launch=App.LAUNCH_INTERFACE,
                            remote_engine_host='localhost', remote_engine_port=60000)
        app_interface.run()
    except Exception as e:
        q.put(e)


@pytest.fixture(scope="function")
def relative_path():
    yield '..'


def test_execute_one_loop_all_remote(base_directory):
    exception_q = multiprocessing.Queue()

    p_serv = multiprocessing.Process(target=_thread_server_func, args=(exception_q, base_directory,))
    p_client = multiprocessing.Process(target=_thread_client_func, args=(exception_q, base_directory,))
    p_serv.start()
    time.sleep(0.1)
    p_client.start()
    p_serv.join()
    p_client.join()

    assert exception_q.empty()


def test_execute_one_loop_all_remote_with_search(base_directory):
    exception_q = multiprocessing.Queue()

    p_serv = multiprocessing.Process(target=_thread_server_func, args=(exception_q, base_directory,))
    p_client = multiprocessing.Process(target=_thread_client_search_remote_func, args=(exception_q, base_directory,))
    p_serv.start()
    time.sleep(0.1)
    p_client.start()
    p_serv.join()
    p_client.join()

    assert exception_q.empty()


def test_execute_one_loop_local_and_remote(base_directory):
    exception_q = multiprocessing.Queue()

    p_serv = multiprocessing.Process(target=_server_func, args=(exception_q, base_directory,))
    p_client = multiprocessing.Process(target=_client_func, args=(exception_q, base_directory,))
    p_serv.start()
    time.sleep(0.1)
    p_client.start()
    p_serv.join()
    p_client.join()

    exception_q.empty()


# must be at the end to avoid  test_execute_one_loop_all_remote() freeze ??
def test_execute_one_loop_threaded(base_directory):
    app = App(InterfaceMock,
              root_path=base_directory,
              config_path=os.path.join(base_directory, 'integration/config', 'game_two_agents'))
    try:
        app.run()
    except Exception:
        assert False
    else:
        assert True
