#!/usr/bin/env python
#
# Data Quality Checker also known as DQC
#
# Read the README.md for more detailed information
#
#       Barcelona Supercomputing Center - Centro Nacional de Supercomputacion
#       Earth Sciences Department - Computational Earth Sciences
#
#     Authors:
#       Joan Sala Calero (joan.sala@bsc.es)

import datetime
import sqlite3
from sqlite3 import Error

"""
Create SQLite DB connection to file
"""
def create_connection(db_file):

    conn = None
    try:
        conn = sqlite3.connect(db_file)

    except Error as e:
        print(e)

    return conn

"""
-- Main database table
CREATE TABLE dataset (
	"_datasetId" TEXT PRIMARY KEY,
	"datasetGroup" TEXT,
	"lastUpdated" TEXT
);
"""
def insert_dataset(conn, _datasetId, datasetGroup):

    lastUpdated = datetime.datetime.now().isoformat()
    sql = '''INSERT INTO dataset(_datasetId, datasetGroup, lastUpdated)
             VALUES("{}","{}","{}") '''.format(_datasetId, datasetGroup, lastUpdated)
    cur = conn.cursor()
    cur.execute(sql)
    conn.commit()

    return cur.lastrowid

"""
-- Stores all files for a dataset X (normally a file per month)
CREATE TABLE file (
	"_fname" TEXT,
	"downRequired" INTEGER,
	-- Foreign keys
	"_ds" TEXT,
	FOREIGN KEY (_ds) REFERENCES dataset(_datasetId),
	PRIMARY KEY (_fname, _ds)
);
"""
def insert_files(conn, datasetId, cds_forms_dates, cds_variable, origin, system):

    # Perform download (2 months per year, those months change per variable(m))
    startM = len(cds_variable) % 6 + 1
    endM = (startM + 6)
    count = 0
    files = []

    dates_to_download = []
    for yr in range(cds_forms_dates[0].year, cds_forms_dates[-1].year + 1):
        if yr < 2020:
            mstart = 1 + (startM + count) % 12
            mend = 1 + (endM + count) % 12
            dates_to_download.append('{}{:02}01'.format(yr, mstart))
            dates_to_download.append('{}{:02}01'.format(yr, mend))
            count += 1

    # Go through all cds-forms dates, extract month and mark for download
    for dt in cds_forms_dates:

        # We store all data per month YYYYMMDD
        fnameDate = dt.strftime('%Y%m01')
        year = int(dt.strftime('%Y'))
        if 'seasonal' in datasetId:
            fname = "{o}-{s}-{dt}".format(dt=fnameDate, o=origin, s=system)
        else:
            if 'uerra' in datasetId:
                fname = "{o}-{dt}".format(dt=fnameDate, o=origin)
            else:
                fname = "{v}-{dt}".format(dt=fnameDate, v=cds_variable)

        # 2 months per year strategy for hourly products - before Jan2020
        downRequired = 1
        if not('monthly' in datasetId) and not(fnameDate in dates_to_download) and year<2020:
            downRequired = 0

        # Insert or replace (avoid double entries)
        sql = '''INSERT OR REPLACE INTO file(_fname, downRequired, _ds)
                 VALUES("{}", {}, "{}")'''.format(fname, downRequired, datasetId)
        files.append(fname)

        cur = conn.cursor()
        cur.execute(sql)
        conn.commit()

    return files

"""
-- Each file has T timestamps (this table is filled and used by the temporal_completeness and temporal_consistency checks)
CREATE TABLE filedatetime (
	"_timestamp" TEXT,
	-- Foreign keys
	"_ds" TEXT,
	"_fn" TEXT,
	FOREIGN KEY (_ds) REFERENCES dataset(_datasetId),
	FOREIGN KEY (_fn) REFERENCES file(_fname),
	PRIMARY KEY (_ds, _fn, _timestamp)
);
"""
def insert_filedatetime(conn, _timestamp, _fn, _ds):

    sql = '''INSERT INTO filedatetime(_timestamp, _fn, _ds)
             VALUES("{}","{}","{}") '''.format(_timestamp, _fn, _ds)
    cur = conn.cursor()
    cur.execute(sql)
    conn.commit()

    return cur.lastrowid

"""
-- Each file goes through D datachecks (standard_compliance, spatial_completeness, ... , valid_ranges)
CREATE TABLE filedatacheck (
	"_checkId" TEXT,
	"checkResult" INTEGER DEFAULT 0,
	"checkMsg"	INTEGER,
	-- Foreign keys
	"_ds" TEXT,
	"_fn" TEXT,
	FOREIGN KEY (_ds) REFERENCES dataset(_datasetId),
	FOREIGN KEY (_fn) REFERENCES file(_fname),
	PRIMARY KEY (_ds, _fn, _checkId)
);
"""
def insert_filedatacheck(conn, _ds, _fn, _checkId, checkResult, checkMsg):

    sql = '''INSERT INTO filedatacheck(_ds, _fn, _checkId, checkResult, checkMsg)
             VALUES("{}","{}","{}","{}","{}") '''.format(_ds, _fn, _checkId, checkResult, checkMsg)
    cur = conn.cursor()
    cur.execute(sql)
    conn.commit()

    return cur.lastrowid

def update_filedatacheck(conn, _ds, _fn, _checkId, checkResult, checkMsg):

    sql = '''UPDATE filedatacheck
             SET checkResult="{}", checkMsg="{}"
             WHERE _ds="{}" AND _fn="{}" AND _checkId="{}";'''.format(checkResult, checkMsg, _ds, _fn, _checkId)
    cur = conn.cursor()
    cur.execute(sql)
    conn.commit()

    return cur.lastrowid