#!/usr/bin/env python
#
# Data Quality Checker also known as DQC
#
# Read the README.md for more detailed information
#
# Barcerlona Supercomputing Center - Centro Nacional de Supercomputacion
#        Earth Sciences Department - Computational Earth Sciences
#     
#     Authors: Ivan Jose Cernicharo Ortiz (ivan.cernicharo@bsc.es)
#             -
#             -
#

import sys
import logging
import os
import subprocess

# Check grid description, 1 degree or whatelse
# This will be checked using CDO

###############################################################################
# Function to manage CDO output and to return grid shape, resolution, etc
def return_cdoinfo(file_name):
    b = CDO.sinfo(input=file_name)
    points = [e for e in b if 'points' in e][0]
    grid_shape = [e for e in points.split(':')[-1].strip().split(' ') if ('x' in e and '(' in e and ')' in e)][0].replace('(','').replace(')','')
    grid_shape_tup = (int(grid_shape.split('x')[0]),int(grid_shape.split('x')[0]))
    grid_num_points = int(points.split(':')[-1].strip().split(' ')[0].replace('points=',''))
    grid_type = points.split(':')[1].strip()

    def return_lat_lon(b):
        if grid_type == 'lonlat':
            resolution_lat=[e for e in b if ('degrees' in e and 'by' in e and 'lat' in e)][0].split(':')[-1].strip().split(' ')
            resolution_lon=[e for e in b if ('degrees' in e and 'by' in e and 'lon' in e)][0].split(':')[-1].strip().split(' ')
            lati = (
                float(resolution_lat[0]),
                float(resolution_lat[2]),
                float(resolution_lat[4])
            )
            long = (
                float(resolution_lon[0]),
                float(resolution_lon[2]),
                float(resolution_lon[4])
            )
        else:
            if any('lat :' in element for element in b) and any('lon :' in element for element in b):
                lat=[e for e in b if 'lat :' in e][0].split(':')[-1].strip().split(' ')
                lon=[e for e in b if 'lon :' in e][0].split(':')[-1].strip().split(' ')
                if len(lat) > 4:
                    lati = (
                        float(lat[0]),
                        float(lat[2]),
                        float(lat[4])
                    )
                else:
                    lati = (
                        float(lat[0]),
                        float(lat[2])
                    )
                if len(lon) > 4:
                    long = (
                        float(lon[0]),
                        float(lon[2]),
                        float(lon[4])
                    )
                else:
                    long = (
                        float(lon[0]),
                        float(lon[2])
                    ) 
            if any('latitude' in element for element in b) and any('longitude' in element for element in b):
                lat=[e for e in b if 'latitude' in e][0].split(':')[-1].strip().split(' ')
                lon=[e for e in b if 'longitude' in e][0].split(':')[-1].strip().split(' ')
                if len(lat) > 4:
                    lati = (
                        float(lat[0]),
                        float(lat[2]),
                        float(lat[4])
                    )
                else:
                    lati = (
                        float(lat[0]),
                        float(lat[2])
                    )
                if len(lon) > 4:
                    long = (
                        float(lon[0]),
                        float(lon[2]),
                        float(lon[4])
                    )
                else:
                    long = (
                        float(lon[0]),
                        float(lon[2])
                    )
                # if any('mapping' in a for a in b):
                #     mapping = [e for e in b if 'mapping :' in e][0].split(':')[-1].strip()
                # if any('x :' in a for a in b) and any('y :' in a for a in b):
                #     x = [e for e in b if 'x :' in e][0].split(':')[-1].strip().split(' ')
                #     y = [e for e in b if 'y :' in e][0].split(':')[-1].strip().split(' ')
                #     xb = (
                #         x[0],
                #         x[2],
                #         x[4]
                #     )
                #     yb = (
                #         y[0],
                #         y[2],
                #         y[4]
                #     )
        return lati,long

    final_object = list()

    final_object.append(grid_shape_tup)
    final_object.append(grid_num_points)
    print(grid_type)
    # The important elements we will use are the ones above, next ones are optional

    try:
        lati,long = return_lat_lon(b)
        final_object.append(lati)
        final_object.append(long)    

    except:
        pass

    return final_object

    # It is unfinished, needs to be included in the workflow, to configure the
    # output properly and to remove the print statements

###############################################################################

class spatial_consistency_test:

    def __init__(self,path,type=None):
        self.type = type
        self.path = path
        self.files = self.list_files_folder()

    def list_files_folder(self):
        list_files = []
        
        if os.path.exists(self.path) and os.path.isdir(self.path):
            for root, dirs, files in os.walk(self.path):
                    for f in files:
                        if f.endswith("grib") or f.endswith("nc"):
                            list_files.append(os.path.join(root,f))
            
            return sorted(list_files)
        else:
            raise Exception('\n\tGiven path is not a valid path\n')

    def check(self,args):
        import cdo
        CDO = cdo.Cdo()

        for filename in args:
            return_cdoinfo(filename)


    def initiate_logging(self):
        # Initiate the logging
        time0 = self.timefortitle
        path_logs = os.path.join(
            '/data',
            'DQC_LOGS'
        )

        if not os.path.exists(path_logs):
            os.makedirs(path_logs)

        default_log_name = '_'.join(
            [
                'LOG_TEST04_SPATIAL_CONSISTENCY_CHECK',
                (self.type).upper(),
                time0,
                '.log'
            ]
        )

        default_path = os.path.join(
            path_logs,
            default_log_name
        )
        
        logging.basicConfig(
            filename=default_path,
            format='%(levelname)s:%(asctime)s:%(message)s', 
            level=logging.INFO
        )

        stringA = '\n' + '#'*80 + '\n' + '#'*80
        stringA += '\n RUNNING SPATIAL CONSISTENCY TEST FOR FOLDER:'
        stringA += '\n ' + self.path
        stringA += '\n AGAINST ' + (self.type).upper() + ' DQC '
        stringA += '\n EXECUTION TIME: ' + self.timeforinfo
        stringA += '\n' + '#'*80

    def main(self):
        if self.type != None:

            listfiles = []

            if self.type == 'netcdf':
                listfiles = [item for item in self.files if item.endswith('.nc')]

            if self.type == 'grib':
                listfiles = [item for item in self.files if item.endswith('.grib')]

            if listfiles != []:
                self.check(self,listfiles)
            else:
                raise Exception('No files in the given input')

        else:
            sys.exit()

if __name__ == "__main__":
    sys.exit()
