import unittest
import asyncio

from pathlib import Path
import sys
import logging
logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(asctime)s %(name)s %(levelname)s: %(message)s')
logger = logging.getLogger(__name__)

from src.millconnect.project import Project
from src.millconnect.server import listen, sendProject, awaitNewOrder, confirmNewOrder, handleConnection

class ServerTest(unittest.IsolatedAsyncioTestCase):

    async def test_sendOrder(self):
        async def handleOrderCreation(websocket, running):

            project = Project(Path('tests/samples/86208'))

            await sendProject(websocket, project)

            running.set_result(False)


        while True:
            running = asyncio.get_running_loop().create_future()
            server = await listen('localhost', 8765, lambda x: handleOrderCreation(x, running))
            logger.info('Started server')

            try:
                await running
                server.close()
            except KeyboardInterrupt:
                break

    async def test_createOrder(self):
        async def handleOrderCreation(websocket, running):

            project = Project(Path('tests/samples/86208'))

            await sendProject(websocket, project)
            confirmedOrder = await awaitNewOrder(websocket)
            project.update(confirmedOrder['order'])
            await confirmNewOrder(websocket)

        while True:
            running = asyncio.get_running_loop().create_future()
            server = listen('localhost', 8765, lambda x: handleOrderCreation(x, running))
            logger.info('Started server')

            try:
                await running
                server.close()
            except KeyboardInterrupt:
                break

    async def test_port_used(self):
        server1 = listen('localhost', 8765, handleConnection)
        logger.info('started first server')

        with self.assertLogs(level='WARNING') as cm:
            server2 = listen('localhost', 8765, handleConnection)

        logger.info('started second server')
        self.assertIn('WARNING:src.millconnect.server:Failed to start server (localhost:8765), try using next port number: [Errno 98] Address already in use (while attempting to bind on address (\'localhost\', 8765))', cm.output)

        self.assertGreater(server1.fileno(), 0)
        self.assertGreater(server2.fileno(), 0)

        server1.shutdown()
        server2.shutdown()

        self.assertEqual(server1.fileno(), -1)
        self.assertEqual(server2.fileno(), -1)

    async def test_all_ports_used(self):
        servers = []
        for i in range(7):
            server = listen('localhost', 8765, handleConnection)
            logger.info(f'started server {i+1}')
            servers.append(server)

