"""A class for creating LineSpectrum data"""

# Imports from cassis
from eu.omp.irap.cassis.gui.plot.tools import ToolsUtil
from eu.omp.irap.cassis.common         import UtilArrayList

# Imports from Python
import os


def differential(y):
    """Return the diffential values"""
    return map(lambda b, a: abs(b - a), y[1:], y[0:-1])


def flatten(l):
    """Flatten a list l"""
    return [item for sublist in l for item in sublist]


class LineSpectrumData(object):
    """The data necessary for plotting a LineSpectrum

    Parameters
    ----------
    frequency : list
        A list of list of frequencies
    velocity : list
        A list of list of velocities
    intensity : list
        A list of list of intensities
    vlsr : float
        The velocity in the local standard of rest of the data
    """

    def __init__(self, frequency, velocity, intensity, vlsr):
        self.frequency    = frequency
        self.velocity     = velocity
        self.intensity    = intensity
        self.overSampling = 1
        self.vlsr         = vlsr
        self.deltaF       = self.calculateDelta(self.frequency)
        self.deltaV       = self.calculateDelta(self.velocity)

        # Checks
        self.checkConsistency()

        self.nbOfLines = sum(len(frequency) for frequency in self.frequency)

        # Columns
        self.createColumns()

    def createColumns(self):
        self.columns            = {}
        self.columns["FreqLsb"] = flatten(self.frequency)
        self.columns["VeloLsb"] = flatten(self.velocity)
        self.columns["FreqUsb"] = [0.0] * self.nbOfLines
        self.columns["VeloUsb"] = [0.0] * self.nbOfLines
        self.columns["Int"]     = flatten(self.intensity)
        self.columns["DeltaF"]  = flatten(self.deltaF)
        self.columns["DeltaV"]  = flatten(self.deltaV)

    def checkConsistency(self):
        msg = "Frequency, velocity and intensity must have the same dimension.\n"
        msg += "Frequency [%d], velocity [%d], intensity [%d]."

        assert len(self.frequency) == len(self.velocity) == len(self.intensity), msg % (len(self.frequency),
                                                                                        len(self.velocity),
                                                                                        len(self.intensity))

        msg = "Frequency, velocity and intensity must have the same length.\n"
        msg += "Frequency [%d], velocity [%d], intensity [%d]."
        for i in range(len(self.intensity)):
            assert len(self.frequency[i]) == len(self.velocity[i]) == len(self.intensity[i]), msg % (len(self.frequency[i]),
                                                                                                     len(self.velocity[i]),
                                                                                                     len(self.intensity[i]))

    def calculateDelta(self, x):
        """Return the delta values for the given input"""
        delta = map(differential, x)

        # Append arbitrarily the last delta value to each list
        # for consistency with the initial input
        for i in range(len(delta)):
            delta[i].append(delta[i][-1])
        return delta

    def applyOverSampling(self, overSampling):
        self.overSampling       = overSampling
        self.resampledFrequency = []
        self.resampledVelocity  = []
        self.resampledIntensity = []
        #
        for i in range(len(self.intensity)):
            self.resampledFrequency.append(UtilArrayList.oversample(self.frequency[i], self.overSampling))
            self.resampledVelocity.append(UtilArrayList.oversample(self.velocity[i], self.overSampling))

            # For some reason the resampling cannot process decreasing scales
            # so we have to sort them to make sure they are increasing
            resampledIntensity = ToolsUtil.resample(sorted(self.resampledVelocity[i]), sorted(self.velocity[i]), self.intensity[i])
            self.resampledIntensity.append(list(resampledIntensity))

        # Update the inputs
        self.nbOfLines = sum(len(freq) for freq in self.resampledFrequency)
        self.frequency = self.resampledFrequency
        self.velocity  = self.resampledVelocity
        self.intensity = self.resampledIntensity
        self.deltaF    = self.calculateDelta(self.frequency)
        self.deltaV    = self.calculateDelta(self.velocity)

        # Columns
        self.createColumns()

    def saveToFile(self, filename):
        """docstring for writeToFile"""
        if os.path.exists(filename):
            os.remove(filename)

        f = open(filename, "a")
        f.write("// number of line : %d\n" % self.nbOfLines)
        f.write("// vlsr : %.2f\n" % self.vlsr)
        f.write("FreqLsb VeloLsb FreqUsb VeloUsb Int DeltaF DeltaV\n")

        for i in xrange(self.nbOfLines):
            f.write("%f\t%f\t%3.2f\t%3.2f\t%f\t%f\t%f\t\n" % (self.columns["FreqLsb"][i],
                                                              self.columns["VeloLsb"][i],
                                                              self.columns["FreqUsb"][i],
                                                              self.columns["VeloUsb"][i],
                                                              self.columns["Int"][i],
                                                              self.columns["DeltaF"][i],
                                                              self.columns["DeltaV"][i]))
        f.close()
        print("Saved %s." % filename)


