#!/usr/bin/env python
#
# grib_checker.py checks Checks whatever you want to check in your life
#
# AUTHOR: BSC-CNS I. CERNICHARO
#

import sys
import numpy as np
import eccodes as ecc
import logging

import data_checks
import metadata_checks

class grib_content:
    """grib_content object class set a list of checks and properties where
    the content of a grib file will be evaluated. All it needs to initiate
    is the file path of the GRIB file we will evaluate
    """
    def __init__(self,filename):
        self.name = filename
        self.grib_msgs = self.return_all_msg()
        self.pname = filename.split("/")[-1]
        self.log = ''

    def return_all_msg(self):
        # This funtion returns all messages within a GRIB file
        all_mssg = list()
        content = ecc.GribFile(self.name)
        
        for i in range(len(content)):
            all_mssg.append(ecc.GribMessage(content))

        return all_mssg


    def print_num_keys(self):
        # It returns the file name without the path
        HEAD = "#NUM MSGs: "
        if len(HEAD) != 24: 
            HEAD += (24-len(HEAD))*" "
        mssg = HEAD +str(len(self.grib_msgs))+" messages"
        logging.info(mssg)

    def check_data_coords(self):
        # The following lists will be filled with the log report for each
        # message. Coordinates and data values will be tested
        coords_log = list()
        data_log = list()
        index = list()

        # Checking all messages. Here we call methods that are imported from
        # data_checks submodule
        for i,msg in enumerate(self.grib_msgs):
            coords_log.append(data_checks.check_coords(msg))
            data_log.append(data_checks.check_data_values(msg))
            index.append(i)
        
        err_coords = coords_log.count("ERROR")
        err_data = data_log.count("ERROR")

        if err_coords != 0:
            HEAD = "#VAR_COORDS >> WARNING: "
            if len(HEAD) != 24: 
                HEAD += (24-len(HEAD))*" "
            msg_coord = "\n" + "One or more messages have incorrect data"
            logging.warning(msg_coord)
        else:
            HEAD = "#VAR_COORDS >> INFO: "
            if len(HEAD) != 24: 
                HEAD += (24-len(HEAD))*" "
            msg_coord = "\n" + "Everything OK with coordinates"
            logging.info(msg_coord)

        if err_data != 0:
            HEAD = "#VAR_DATA >> WARNING: "
            if len(HEAD) != 24: 
                HEAD += (24-len(HEAD))*" "
            msg_data = "\n" + "One or more messages have incorrect data"
            logging.warning(msg_data)
        else:
            HEAD = "#VAR_DATA >> INFO: "
            if len(HEAD) != 24: 
                HEAD += (24-len(HEAD))*" "
            msg_data = "\n" + "Everything OK with data values"
            logging.info(msg_data)

    def check_meta_grid(self):
        # The following lists will be filled with the log report for each
        # message. Metadata of the header and of the grid description section
        # will be tested.
        meta_log = list()
        grid_log = list()
        index = list()
        # These lists, g_ed and grid_t will check the homogeneity of the 
        # messages for the GRIBEditionNumber and gridType keys.
        g_ed = list()
        grid_t = list()
        missing_meta = list()
        missing_grid = list()

        # Checking all messages. Here we call methods that are imported from
        # metadata_checks submodule

        for i,msg in enumerate(self.grib_msgs):

            index.append(i)

            g_ed.append(msg["GRIBEditionNumber"])
            grid_t.append(msg["gridType"])

            meta_cck = metadata_checks.check_metada_keys(msg)
            grid_cck = metadata_checks.check_grid_keys(msg)

            if len(meta_cck) > 1:
                for item in meta_cck[1]:
                    if item not in missing_meta:
                        missing_meta.append(item)

            if len(grid_cck) > 1:
                for item in grid_cck[1]:
                    if item not in missing_grid:
                        missing_grid.append(item)

            meta_log.append(meta_cck[0])
            grid_log.append(grid_cck[0])

        grib_editions = list(set(g_ed))
        grid_types = list(set(grid_t))
        
        err_meta = meta_log.count("ERROR")
        err_grid = grid_log.count("ERROR")

        if len(grib_editions) > 1:
            import warnings
            # There are more than 1 edition in gribEdition keys for GRIB messages
            if 1 not in grib_editions:
                # If edition 1 not in
                msg_editions = "\n" + "Grib Edition Check:"
                msg_editions += "\n" + "tFound different Grib editions in the messages"
                for item in grib_editions:
                    msg_editions += "\n" + "\t\tEdition: " + str(item)
                logging.warning(msg_editions)
            else:
                msg_editions = "\n" + "Grib Edition Check:"
                msg_editions += "\n" + "tFound different Grib editions in the messages"
                for item in grib_editions:
                    msg_editions += "\n" + "\t\tEdition: " + str(item)
                wrn = "Deprecated GRIB1 version found"
                msg_editions += "\n\t" + wrn
                warnings.warn(wrn)
                logging.warning(msg_editions)
        else:
            if 1 not in grib_editions:
                msg_editions = "\n" + "Grib Edition Check:"
                msg_editions += " Everything OK, one unique edition found"
                msg_editions += " GRIB" + str(grib_editions[0])
                logging.info(msg_editions)
            else:
                msg_editions = " Grib Edition Check: "
                msg_editions += "Deprecated GRIB1 version found"
                logging.warning(msg_editions)
                warn_msg = "#KEYS-GRIB_ED >> WARNING: " + msg_editions
                wrn = "Deprecated GRIB1 version found"
                warnings.warn(wrn)

        if len(grid_types) > 1:
            msg_grid_type = "\n" + "Grid Type Check:"
            msg_grid_type += "\n" + "\tFound different Grid Type in the messages"
            for item in grid_types:
                msg_grid_type += "\n" + "\t\tGrid type: " + str(item)
            logging.warning(msg_grid_type)
        else:
            msg_grid_type = "\n" + "Grid Type Check:"
            msg_grid_type += "\n" + "\tEverything OK, one unique Grid Type found"
            msg_grid_type += "\n" + "\t\tGrid type: " + str(grid_types[0])
            logging.info(msg_grid_type)

        if err_meta != 0:
            msg_meta = "\n" + "Metadata Check:"
            msg_meta += "\n" + "\tOne or more messages have missing KEYS"
            for item in missing_meta:
                msg_meta += "\n" + "\t\tKey: " + str(item)
            logging.warning(msg_meta)
        else:
            msg_meta = "\n" + "Metadata Check:"
            msg_meta += "\n" + "tEverything OK"
            logging.info(msg_meta)

        if err_grid != 0:
            msg_grid = "\n" + "Grid Metada Check:"
            msg_grid += "\n" + "\tOne or more messages have missing Keys"
            for item in missing_grid:
                msg_grid += "\n" + "\t\tKey: " + str(item)
            logging.warning(msg_grid)
        else:
            msg_grid = "\n" + "Grid Metada Check:"
            msg_grid += "\n" + "\tEverything OK with data values"
            logging.info(msg_grid)

        # STILL WORKING ON THIS
