# coding: utf8

from ase.build import bulk
import numpy as np
from msspec.calculator import MSSPEC, XRaySource
from msspec.utils import hemispherical_cluster, get_atom_index

def create_clusters(nplanes=6):
    def get_AlN_tags_planes(side, emitter):
        AlN = bulk('AlN', crystalstructure='wurtzite', a=3.11, c=4.975)
        [atom.set('tag', i) for i, atom in enumerate(AlN)]
        if side == 'Al':
            AlN.rotate([0,0,1],[0,0,-1])
            Al_planes = range(0, nplanes, 2)
            N_planes  = range(1, nplanes, 2)
        else:
            N_planes  = range(0, nplanes, 2)
            Al_planes = range(1, nplanes, 2)
        if emitter == 'Al':
            tags = [0, 2]
            planes = Al_planes
        else:
           tags = [1, 3]
           planes = N_planes
        return AlN, tags, planes

    clusters = []
    for side in ('Al', 'N'):
        for emitter in ('Al', 'N'):
            AlN, tags, planes = get_AlN_tags_planes(side, emitter)
            for emitter_tag in tags:
                for emitter_plane in planes:
                    cluster = hemispherical_cluster(AlN,
                                                    emitter_tag=emitter_tag,
                                                    emitter_plane=emitter_plane,
                                                    planes=emitter_plane+2)
                    cluster.absorber = get_atom_index(cluster, 0, 0, 0)
                    cluster.info.update({
                        'emitter_plane': emitter_plane,
                        'emitter_tag'  : emitter_tag,
                        'emitter'      : emitter,
                        'side'         : side,
                    })
                    clusters.append(cluster)
                    print("Added cluster {}-side, emitter {}(tag {:d}) in "
                          "plane #{:d}".format(side, emitter, emitter_tag,
                                               emitter_plane))
    return clusters


def compute(clusters, theta=np.arange(-20., 80., 1.), phi=0.):
    data = None
    for ic, cluster in enumerate(clusters):
        # Retrieve info from cluster object
        side    = cluster.info['side']
        emitter = cluster.info['emitter']
        plane   = cluster.info['emitter_plane']
        tag     = cluster.info['emitter_tag']

        # Set the level and the kinetic energy
        if emitter == 'Al':
            level = '2p'
            ke    = 1407.
        elif emitter == 'N':
            level = '1s'
            ke    = 1083.

        calc = MSSPEC(spectroscopy='PED', algorithm='expansion')

        calc.source_parameters.energy = XRaySource.AL_KALPHA
        calc.source_parameters.theta  = -35

        calc.detector_parameters.angular_acceptance = 4.
        calc.detector_parameters.average_sampling   = 'medium'

        calc.calculation_parameters.scattering_order = max(1, min(4, plane))
        calc.calculation_parameters.path_filtering  = 'forward_scattering'
        calc.calculation_parameters.off_cone_events = 1
        [a.set('forward_angle', 30.) for a in cluster]

        calc.set_atoms(cluster)

        data = calc.get_theta_scan(level=level, theta=theta, phi=phi,
                                   kinetic_energy=ke, data=data)
        dset = data[-1]
        dset.title = "\'{}\' side - {}({}) tag #{:d}, plane #{:d}".format(
            side, emitter, level, tag, plane)

    return data


def analysis(data):
    tmp_data = {}
    for dset in data:
        info = dset.get_cluster().info
        side = info['side']
        emitter = info['emitter']
        try:
            key = '{}_{}'.format(side, emitter)
            tmp_data[key] += dset.cross_section
        except KeyError:
            tmp_data[key] = dset.cross_section.copy()

    tmp_data['theta']   = dset.theta.copy()
    tmp_data['Al_side'] = tmp_data['Al_Al'] / tmp_data['Al_N']
    tmp_data['N_side']  = tmp_data['N_Al']  / tmp_data['N_N']

    # now add all columns
    substrate_dset = data.add_dset('Total substrate signal')
    substrate_dset.add_columns(**tmp_data)

    view = substrate_dset.add_view('Ratios',
                                   title=r'Al(2p)/N(1s) ratios on both polar '
                                         r'sides of AlN in the (10$\bar{1}$0) '
                                         r'azimuthal plane',
                                   xlabel=r'$\Theta (\degree$)',
                                   ylabel='Intenisty ratio')
    view.select('theta', 'Al_side', legend='Al side',
                where="theta >= 0 and theta <=70")
    view.select('theta', 'N_side', legend='N side',
                where="theta >= 0 and theta <=70")
    view.set_plot_options(autoscale=True)

    return data


clusters = create_clusters()
data     = compute(clusters)
data     = analysis(data)
data.view()
