"""
Layer interactor.
"""
from __future__ import division
from bumps.parameter import Parameter
from refl1d.material import SLD
from .interactor import BaseInteractor
from .config import pick_radius
from .config import rho_color, rhoI_color, disabled_color
from .util import setpar


class MaterialInteractor(BaseInteractor):
    def __init__(self, profile, material, range=(0,1)): #@ReservedAssignment
        super(MaterialInteractor,self).__init__(profile)
        self.material = material
        self.range = range

        if isinstance(material,SLD):
            enabled = True
            self._rho = material.rho
            self._rhoI = material.irho
            self._rho_scale = 1
            self._rhoI_scale = 1
        elif (hasattr(material,'density')
              and isinstance(material.density,Parameter)):
            enabled = True
            rho,rhoI = material.sld(profile.experiment.probe)
            self._rho = material.density
            self._rhoI = material.density
            self._rho_scale = 1/ (rho / material.density.value)
            self._rhoI_scale = 1/ (rhoI / material.density.value)
        else:
            self._rho = self._rhoI = None
            enabled = False

        style = dict(linestyle='--',
                     linewidth  = 2,
                     pickradius = pick_radius,
                     )
        ax = profile.axes
        rho = ax.plot([], [], label=material.name+" rho",
                      color=rho_color if enabled else disabled_color,
                      zorder=6, **style)[0]
        rhoI = ax.plot([], [], label=material.name+" rhoI",
                      color=rhoI_color if enabled else disabled_color,
                      zorder=5, **style)[0]

        self.markers = [rho,rhoI]
        if enabled:
            self.connect_markers(self.markers)

    def update_markers(self):
        z = self.profile.boundary[1:-1]
        n = self.profile.layer_num
        #if n is None: return
        if n == 0:
            left,right = -20,0
        elif n >= len(z):
            left,right = z[-1],z[-1]+20
        else:
            delta = z[n] - z[n-1]
            left,right = self.range[0]*delta+z[n-1], self.range[1]*delta+z[n-1]

        rho,rhoI = self.material.sld(self.profile.experiment.probe)
        self.markers[0].set_data( (left,right), (rho,rho) )
        self.markers[1].set_data( (left,right), (rhoI,rhoI) )

    def save(self, ev):
        if self._rho is not None: self._rho_save = self._rho.value
        if self._rhoI is not None: self._rhoI_save = self._rhoI.value

    def restore(self, ev):
        if self._rho is not None: self._rho.value = self._rho_save
        if self._rhoI is not None: self._rhoI.value = self._rhoI_save

    def drag(self, ev):
        if ev.artist == self.markers[0]:
            setpar(self._rho, ev.ydata * self._rho_scale)
        else:
            setpar(self._rhoI, ev.ydata * self._rhoI_scale)

class SlabInteractor(BaseInteractor):
    def __init__(self, profile, layer):
        super(SlabInteractor,self).__init__(profile)
        self.material = MaterialInteractor(profile,layer.material)
    def update_markers(self):
        self.material.update_markers()
    def clear_markers(self):
        self.material.clear_markers()


# -------------------------------------------------------------------
class NoInteractor(BaseInteractor):
    """
    Null Interactor for undefined layers.
    """
    def __init__(self, profile, layer):
        super(NoInteractor,self).__init__(profile)
    # TODO: turn layer.parameters() into sliders
