import time
from scipy.interpolate import LinearNDInterpolator
from itertools import product
import numpy as np

def utc2mjd(year,month,day,hour,minute,second):
    """docstring for utc2mjd"""
    t2000 = time.mktime((2000, 1, 1, 0, 0, 0, 0, 0, 0)) - time.timezone
    t = time.mktime((year, month, day, hour, minute, 0, 0, 0, 0)) -time.timezone
    result = (t+ second -t2000)/(86400)
    return result

def mjd2utc(mjd):
    """docstring for utc2mjd"""
    t2000 = time.mktime((2000, 1, 1, 0, 0, 0, 0, 0, 0)) -time.timezone
    t=(mjd)*(86400.0) +t2000
    gmt=time.gmtime(t)
    result={"year":gmt[0],"month":gmt[1], "day":gmt[2], "hour":gmt[3], "minute":gmt[4], "second":gmt[5]+ t%1}
    return result

def interpolator(coords, data, point) :
    dims=len(point)
    indices=[]
    sub_coords=[]
    for j in xrange(dims) :
        idx = np.digitize([point[j]], coords[j])[0]
        if idx == len(coords[j]):
            idx-=1
        indices += [[idx - 1, idx]]
        sub_coords += [coords[j][indices[-1]]]
    indices = np.array([j for j in product(*indices)])
    sub_coords = np.array([j for j in product(*sub_coords)])
    sub_data = data[list(np.swapaxes(indices, 0, 1))]

    li = LinearNDInterpolator(sub_coords, sub_data)
    return li([point])[0]

def intweight(coords,point):
    dims=len(point)
    indices=[]
    sub_coords=[]
    weights=[]
    for j in xrange(dims) :
        idx = np.digitize([point[j]], coords[j])[0]
        nn=len(coords[j])
        if idx >= nn:
            idx=nn-1
        indices += [[idx - 1, idx]]
        sub_coords += [coords[j][indices[-1]]]
        w=(coords[j][idx] - point[j])/(coords[j][idx] - coords[j][idx-1])
        weights+=[[w,1-w]]
    indices = np.array([j for j in product(*indices)])
    sub_coords = np.array([j for j in product(*sub_coords)])
    weights = np.array([np.prod(j) for j in product(*weights)])
    sel=weights>0
    return {"idx":indices[sel],"coords":sub_coords[sel],"weights":weights[sel]}


def resample_ts_bi(data, dmjd, dlat, dlon, mjd, lat, lon):
    """Resample (spatially and temporally) data on satellite footprint (sample over grid) using bilinear interpolation """

    npos=len(lat)
    result =[]

#    print data

    for x in data:
        if len(x.shape)==3 : result.append(0.0)                   #  scalar
        else:  result.append(np.zeros(len(x[0,:,0,0])))           #  vector

    for i in range(npos):
        latp=lat[i]
        lonp=lon[i]
        rs=intweight((dmjd, dlat, dlon),(mjd,latp,lonp))

        for j in range(len(rs["idx"])):
            idx = rs["idx"][j]
            weight = rs["weights"][j]
            k = 0
            for x in data:
                if len(x.shape)==3: result[k] = result[k] + x[idx[0],idx[1],idx[2]]*weight #  scalar
                else:  result[k] = result[k] + x[idx[0],:,idx[1],idx[2]]*weight            #  vector
                k +=1

    for k in range(len(result)):
        result[k] = result[k]/npos

    return result


def resample_s_bi(data, dlat, dlon, lat, lon):
    """Resample (spatially) data on satellite footprint (sample over grid) using bilinear interpolation """

    npos=len(lat)
    result =[]

    for x in data:
        if len(x.shape)==2 : result.append(0.0)                   #  scalar
        else:  result.append(np.zeros(len(x[:,0,0])))           #  vector

    for i in range(npos):
        latp=lat[i]
        lonp=lon[i]
        rs=intweight((dlat, dlon),(latp,lonp))

        for j in range(len(rs["idx"])):
            idx = rs["idx"][j]
            weight = rs["weights"][j]
            k = 0
            for x in data:
                if len(x.shape)==2: result[k] = result[k] + x[idx[0],idx[1]]*weight #  scalar
                else:  result[k] = result[k] + x[:,idx[0],idx[1]]*weight            #  vector
                k +=1
    for k in range(len(result)):
        result[k] = result[k]/npos

    return result


def resample_ts_nn(data, dmjd, dlat, dlon, mjd, lat, lon):
    """Resample temporal/spatial data on satellite footprint (sample over grid) using nearest neighbours for space and interpolation for time"""

    npos=len(lat)
    result =[]
    for x in data:
        if len(x.shape)==3 : result.append(0.0)            #scalar
        else:  result.append(np.zeros(len(x[0,:,0,0])))    #vector

    rs=intweight([dmjd],[mjd])
    for i in range(npos):
        latp=lat[i]
        lonp=lon[i]

        ilat =  np.argmin(abs(dlat - latp))
        ilon =  np.argmin(abs(dlon - lonp))
        for j in range(len(rs["idx"])):
            idx = rs["idx"][j]
            weight = rs["weights"][j]
            k = 0
            for x in data:
                if len(x.shape)==3: result[k] = result[k] + x[idx[0],ilat,ilon]*weight #scalar
                else: result[k] = result[k] + x[idx[0],:, ilat,ilon]*weight            #vector
                k +=1

    for k in range(len(result)):
        result[k] = result[k]/npos

    return result


def resample_s_nn(data, dlat, dlon, lat, lon):
    """Resample spatial data on satellite footprint (sample over grid) using nearest neighbours"""

    npos=len(lat)
    result =[]
    for x in data:
        if len(x.shape)==2 : result.append(0.0)
        else:  result.append(np.zeros(len(x[:,0,0])))

    for i in range(npos):
        latp=lat[i]
        lonp=lon[i]
        ilat =  np.argmin(abs(dlat - latp))
        ilon =  np.argmin(abs(dlon - lonp))
        k = 0
        for x in data:
            if len(x.shape)==2: result[k] = result[k] + x[ilat,ilon]
            else: result[k] = result[k] + x[:, ilat,ilon]
            k +=1

    for k in range(len(result)):
        result[k] = result[k]/npos

    return result
