import logging
import pytest

from ophyd import QuadEM, Kind
from ophyd.sim import (make_fake_device, clear_fake_device)
from ophyd.areadetector.plugins import ImagePlugin, StatsPlugin


logger = logging.getLogger(__name__)


@pytest.fixture(scope='function')
def quadem():
    FakeQuadEM = make_fake_device(QuadEM)
    em = FakeQuadEM('quadem:', name='quadem')
    clear_fake_device(em)

    em.conf.port_name.put('NSLS_EM')

    for k in ['image', 'current1', 'current2', 'current3', 'current4',
              'sum_all']:
        cc = getattr(em, k)

        if isinstance(cc, ImagePlugin):
            cc.plugin_type.sim_put(ImagePlugin._plugin_type)
            cc.nd_array_port.sim_put('NSLS_EM')
        elif isinstance(cc, StatsPlugin):
            cc.plugin_type.sim_put(StatsPlugin._plugin_type)
            cc.nd_array_port.sim_put('NSLS_EM')
        else:
            cc.plugin_type.sim_put('unknown')

        cc.enable.sim_set_enum_strs(['Disabled', 'Enabled'])
        cc.enable.put('Enabled')
        cc.port_name.sim_put(k.upper())

    em.wait_for_connection()

    return em


def test_connected(quadem):
    assert quadem.connected


def test_scan_point(quadem):
    assert quadem._staged.value == 'no'

    quadem.stage()
    assert quadem._staged.value == 'yes'

    quadem.trigger()
    quadem.unstage()
    assert quadem._staged.value == 'no'


def test_reading(quadem):
    assert 'current1.mean_value' in quadem.read_attrs

    vals = quadem.read()
    assert 'quadem_current1_mean_value' in vals
    assert (set(('value', 'timestamp')) ==
            set(vals['quadem_current1_mean_value'].keys()))

    rc = quadem.read_configuration()
    dc = quadem.describe_configuration()

    assert quadem.averaging_time.name in rc
    assert quadem.integration_time.name in rc

    assert rc.keys() == dc.keys()


def test_hints(quadem):

    desc = quadem.describe()
    f_hints = quadem.hints['fields']
    assert len(f_hints) > 0
    for k in f_hints:
        assert k in desc

    def clear_hints(dev):
        for c in dev.component_names:
            c = getattr(dev, c)
            c.kind &= ~(Kind.hinted & ~Kind.normal)
            if hasattr(c, 'component_names'):
                clear_hints(c)

    clear_hints(quadem)

    quadem.current1.mean_value.kind = Kind.hinted

    assert quadem.hints == {'fields': ['quadem_current1_mean_value']}
