#!/usr/bin/env python
# coding: utf-8

# Copyright (c) Mito.
# Distributed under the terms of the Modified BSD License.

import pytest

from ipykernel.comm import Comm
from ipywidgets import Widget
from mitosheet.save_utils import _get_all_analysis_filenames, _delete_analyses

class MockComm(Comm):
    """A mock Comm object.

    Can be used to inspect calls to Comm's open/send/close methods.
    """
    comm_id = 'a-b-c-d'
    kernel = 'Truthy'

    def __init__(self, *args, **kwargs):
        self.log_open = []
        self.log_send = []
        self.log_close = []
        super(MockComm, self).__init__(*args, **kwargs)

    def open(self, *args, **kwargs):
        self.log_open.append((args, kwargs))

    def send(self, *args, **kwargs):
        self.log_send.append((args, kwargs))

    def close(self, *args, **kwargs):
        self.log_close.append((args, kwargs))

_widget_attrs = {}
undefined = object()


@pytest.fixture
def mock_comm():
    _widget_attrs['_comm_default'] = getattr(Widget, '_comm_default', undefined)
    Widget._comm_default = lambda self: MockComm()
    _widget_attrs['_ipython_display_'] = Widget._ipython_display_
    def raise_not_implemented(*args, **kwargs):
        raise NotImplementedError()
    Widget._ipython_display_ = raise_not_implemented

    yield MockComm()

    for attr, value in _widget_attrs.items():
        if value is undefined:
            delattr(Widget, attr)
        else:
            setattr(Widget, attr, value)



@pytest.fixture(scope="session", autouse=True)
def cleanup_files():
    """
    This fixture is responsible for cleaning up all saved analyses that result from
    test runs. 

    It does so by reading in all analyses at the start of the testing session, 
    and then removing any new analyses at the end. 

    NOTE: if you use the app while the tests are running, it might delete
    your analyses - but this is really rare!
    """
    # This test runs before 
    old_analysis_filenames = _get_all_analysis_filenames()

    yield # All tests run here

    # This code runs after all the tests
    curr_analysis_filenames = _get_all_analysis_filenames()
    # Find all the new analysis file names (generated by tests)
    new_analysis_filenames = curr_analysis_filenames.difference(old_analysis_filenames)
    # Delete them
    _delete_analyses(new_analysis_filenames)