from __future__ import print_function
from netCDF4 import Dataset
import numpy as np
import os
import time as tm
#from tools import *
#from gp import GroundPixel

class OrbitBase(object):
    """Base class for Orbit"""
    def __init__(self, name):

        self.fileprefix = name
        self.pathtofile = None
        self.filename = None
        self.ncorner = None
        self.lat_corner = None
        self.lat_center = None
        self.lon_corner = None
        self.lon_center = None
        self.sza = None
        self.vza = None
        self.saz = None
        self.vaz = None
        self.mjd = None
        self.utc = None
        self.nobs = None
        self.lat_grid = None
        self.lon_grid = None
        self.tint=None

    # Abstract method, to override in child class
    def read_file(self):
        raise NotImplementedError


    # Get gridpoints for resampling
    def get_grid(self, projection, dx=None, dy=None):

        self.lat_grid = []
        self.lon_grid = []
        for i in range(self.nobs):

            #get lat,lon corners and center of this groundpixel
            lon_pix =[self.lon_center[i],self.lon_corner[i,0],self.lon_corner[i,1],self.lon_corner[i,2],self.lon_corner[i,3]]
            lat_pix =[self.lat_center[i],self.lat_corner[i,0],self.lat_corner[i,1],self.lat_corner[i,2],self.lat_corner[i,3]]

            if projection:
            # sample groundpixel in lat,lon with Lambert azimuthal equal-area projection
                g = GroundPixel((lat_pix[0],lon_pix[0]),[(lat_pix[1],lon_pix[1]), (lat_pix[2],lon_pix[2]),(lat_pix[3],lon_pix[3]),(lat_pix[4],lon_pix[4])])
                p_high = g.get_points(dx, dy)
                # Split p_high into lat, lon
                lati = []
                loni = []
                for j in range(len(p_high)):
                    lati = lati + [p_high[j][0]]
                    loni = loni + [p_high[j][1]]
                self.lat_grid.append(lati)
                self.lon_grid.append(loni)
            else:
            # Only store lat, lon of pixel centers
                self.lat_grid.append([lat_pix[0]])
                self.lon_grid.append([lon_pix[0]])


    def collocate(self, ecmwf=None, tm5ch4=None, tm5co=None, dem=None,modis_land=None, albedo=None,fresco=None, aerosol=None, cloud=None, spatial_resampling='bi', outpath='../OUTPUT/'):

        # Collocate ECMWF
        if ecmwf:
            starttime =  tm.time()
            outfile = outpath+self.fileprefix+"_meteo.nc"
            ecmwf.collocate(self.mjd, self.lat_grid, self.lon_grid, spatial_resampling)
            ecmwf.write_output(outfile)
            print("ECMWF: Output written to "+outpath)
            print('Time needed for ECMWF collocation = {0:.1f} s '.format(tm.time()-starttime))

        # Collocate TM5 CH4
        if tm5ch4:
            starttime =  tm.time()
            outfile = outpath+self.fileprefix+"_ch4.nc"
            tm5ch4.collocate(self.mjd, self.lat_grid, self.lon_grid, spatial_resampling)
            tm5ch4.write_output(outfile)
            print("TM5 CH4: Output written to "+outpath)
            print('Time needed for TM5 CH4 collocation = {0:.1f} s'.format(time.time()-starttime))

        # Collocate TM5 CO
        if tm5co:
            starttime =  tm.time()
            outfile = outpath+self.fileprefix+"_co.nc"
            tm5co.collocate(self.mjd, self.lat_grid, self.lon_grid, spatial_resampling)
            tm5co.write_output(outfile)
            print("TM5 CO: Output written to "+outpath)
            print('Time needed for TM5 CO collocation = {0:.1f} s'.format(tm.time()-starttime))

        # Collocate DEM
        if dem:
            starttime =  tm.time()
            outfile = outpath+self.fileprefix+"_dem.nc"
            dem.collocate(self.mjd, self.lat_grid, self.lon_grid)
            dem.write_output(outfile)
            print("DEM: Output written to "+outpath)
            print('Time needed for DEM collocation = {0:.1f} s'.format(tm.time()-starttime))


         # Collocate MODIS Land COver
        if modis_land:
            starttime =  tm.time()
            outfile = outpath+self.fileprefix+"_land.nc"
            modis_land.collocate(self.lat_grid, self.lon_grid)
            modis_land.write_output(outfile)
            print("MODIS Land Cover: Output written to "+outpath)
            print('Time needed for MODIS Land Cover collocation = {0:.1f} s'.format(tm.time()-starttime))

        # Collocate Albedo
        if albedo:
            starttime =  tm.time()
            outfile = outpath+self.fileprefix+"_albedo.nc"
            albedo.collocate(self.mjd, self.lat_grid, self.lon_grid)
            albedo.write_output(outfile)
            print("Albedo: Output written to "+outpath)
            print('Time needed for Albedo collocation = {0:.1f} s'.format(tm.time()-starttime))

        # Collocate Fresco
        if fresco:
            starttime =  tm.time()
            outfile = outpath+self.fileprefix+"_fresco.nc"
            fresco.collocate(self.mjd, self.tint)
            fresco.write_output(outfile)
            print("Fresco: Output written to "+outpath)
            print('Time needed for Fresco collocation = {0:.1f} s'.format(tm.time()-starttime))

        # Collocate Aerosol files
        if aerosol:
            starttime =  tm.time()
            outfile = outpath+self.fileprefix+"_aerosol.nc"
            aerosol.collocate(self.mjd, self.lat_grid, self.lon_grid)
            aerosol.write_output(outfile)
            print("Aerosol: Output written to "+outpath)
            print('Time needed for Aerosol collocation = {0:.1f} s'.format(tm.time()-starttime))

        # Collocate Modis Aqua clouds.
        if cloud:
            # TODO: Build a wrapper with cloud object.
            starttime = tm.time()
            outfile = outpath+self.fileprefix+"_cloud.nc"
            cloud.collocate(self)
            cloud.write_output(outfile)
            print("Cloud: Output written to "+outpath)
            print('Time needed for cloud collocation = {0:.1f} s'.format(tm.time()-starttime))


    def write_output(self, filename):
        """Write orbit info NetCDF file"""

        # Create NetCDF file
        if os.path.exists(filename):
            os.remove(filename)
        rootgrp = Dataset(filename, 'w', format='NETCDF4')

        #global attributes
        rootgrp.title = "Orbit information"
        rootgrp.institution = "SRON Netherlands Institute for Space Research"
        rootgrp.date_created = tm.ctime(tm.time())

        #create dimensions
        nobs = rootgrp.createDimension('nobs', self.nobs)
        ncorner = rootgrp.createDimension('ncorner', self.ncorner)
        ntime = rootgrp.createDimension('ntime', 7)

        #create variables
        time = rootgrp.createVariable('time', 'i2', ('nobs', 'ntime'))
        lat = rootgrp.createVariable('latitude', 'f4', ('nobs'))
        lon = rootgrp.createVariable('longitude', 'f4', ('nobs'))
        lat_corner = rootgrp.createVariable('latitude_corners', 'f4', ('nobs', 'ncorner'))
        lon_corner = rootgrp.createVariable('longitude_corners', 'f4', ('nobs', 'ncorner'))
        sza = rootgrp.createVariable('solar_zenith_angle', 'f4', ('nobs'))
        vza = rootgrp.createVariable('viewing_zenith_angle', 'f4', ('nobs'))
        vaz = rootgrp.createVariable('viewing_azimuth_angle', 'f4', ('nobs'))
        saz = rootgrp.createVariable('solar_azimuth_angle', 'f4', ('nobs'))

        # Assign an attribute to the dataset
        sza.standard_name = "solar_zenith_angle"
        sza.long_name = "solar zenith angle"
        sza.units = "degree"
        vza.standard_name = "viewing_zenith_angle"
        vza.long_name = "viewing zenith angle"
        vza.units = "degree"
        vaz.standard_name = "viewing_azimuth_angle"
        vaz.long_name = "viewing azimuth angle"
        vaz.units = "degree"
        saz.standard_name = "solar_azimuth_angle"
        saz.long_name = "solar azimuth angle"
        saz.units = "degree"
        time.standard_name = "time_of_measurement"
        time.long_name = "time of measurement since 2000-01-01 00:00:00 "
        time.units = "days since 2000-01-01 00:00:00"
        lat.standard_name = "latitude"
        lat.long_name = "pixel center latitude"
        lat.units = "degrees north"
        lon.standard_name = "longitude"
        lon.long_name = "pixel center longitude"
        lon.units = "degrees east"
        lat_corner.standard_name = "latitude"
        lat_corner.long_name = "pixel corners latitude"
        lat_corner.units = "degrees north"
        lon_corner.standard_name = "longitude"
        lon_corner.long_name = "pixel corners longitude"
        lon_corner.units = "degrees east"

        # Write data

        time[:, :] = self.utc[:,:]
        lat[:] = self.lat_center[:]
        lon[:] = self.lon_center[:]
        lat_corner[:,:] = self.lat_corner[:,:]
        lon_corner[:,:] = self.lon_corner[:,:]
        sza[:] = self.sza[:]
        vza[:] = self.vza[:]
        saz[:] = self.saz[:]
        vaz[:] = self.vaz[:]

        # Close the dataset
        rootgrp.close()






