#!/usr/bin/env python
"""
SYNOPSIS

    ProcessRSData [-h,--help] [-v,--verbose] [--version]

DESCRIPTION

    This script reads a Yaml config file and processes the
    contents. The config file may contain a set of one or
    more 'run' instructions for processing of remote
    sensing data.

EXAMPLES

    TODO: Show some examples of how to use this script.

EXIT STATUS

    TODO: List exit codes

AUTHOR

    Rochelle O'Hagan <spatialexplore@gmail.com>

LICENSE

    This script is in the public domain, free from copyrights or restrictions.

VERSION

    $Id$
"""

import logging
import optparse
import os
import sys
import time
import traceback
from datetime import date

import arcpy
import yaml

import arcPyUtils
from remotesensing import ndviUtils, eviUtils, modisUtils, chirpsUtils#, trmmUtils #.calcLongTermAverageNDVI

#from eviUtils import calcLongTermAverageEVI, calcMonthlyLongTermAverageEVI
#from modisUtils import mosaicMODIS, cropMODIS, extractNDVI, extractEVI, calcLongTermAverageTemp, tranformToWGS84, getMODISDataFromURL
#import chirpsUtils
import rasterUtils
#import trmmUtils
from utilities import directoryUtils
from precipitationAnalysis import calcRainfallAnomaly, daysSinceLast
from vegetationAnalysis import calcVCI, calcTCI, calcTCI_os, calcVHI

logger = logging.getLogger('ProcessRSData')
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG)

def configFileError(msg, e):
    print "Error in config file {0} : {1}".format(msg, str(e))
    return 0

def processExtract(process, config):
    if 'input_dir' in process:
        inw = process['input_dir']
    if 'output_dir' in process:
        outw = process['output_dir']
    if 'input_extension' in process:
        ext = process['input_extension']
    if 'input_prefix' in process:
        prefix = process['input_prefix']
    if 'output_ext' in process:
        output_ext = process['output_ext']
    if 'output_prefix' in process:
        output_prefix = process['output_prefix']
    if 'shapefile' in process:
        shapefile = process['shapefile']
    gdal_path = config['EXTRACT']['directory']['GDAL']
    if ext.endswith(".gz"):
        # need to unzip first
        directoryUtils.unzipFiles(inw, ".gz")
        ext = ext[:-3]
    filenames = (prefix, ext)
    output_filenames = (output_prefix, output_ext)
    rasterUtils.clipRastersInDirToShape(inw, outw, shapefile, filenames, output_filenames, gdal_path)
    return 0

def processCHIRPS(process, cfg):
# legacy variables - these need to be refactored
    prefix = cfg['CHIRPS']['filenames']['input_prefix']
    ext = cfg['CHIRPS']['filenames']['input_extension']
    if 'input_extension' in process:
        ext = process['input_extension']
    if 'input_prefix' in process:
        prefix = process['input_prefix']
    filenames = (prefix, ext)
    if 'input_dir' in process:
        inWks = process['input_dir']
    else:
        inWks = None
    if 'output_dir' in process:
        outWks = process['output_dir']
    else:
        outWks = None
    temp_path = cfg['directory']['temp']
    arcpy.env.workspace = inWks
    if 'functions' in process:
        funcs = process['functions']
    else:
        funcs = None
    if process['type'] == 'longterm_average':
        if process['interval'] == 'monthly':
            print "Processing CHIRPS monthly data"
            chirpsUtils.calcMonthlyAverages(inWks, outWks, funcs, filenames)
        elif process['interval'] == 'seasonal':
            print "Processing CHIRPS seasonal data"
            chirpsUtils.calcSeasonalAverages(inWks, outWks, funcs, filenames)
        elif process['interval'] == 'pentad':
            print "Processing CHIRPS pentad data"
            chirpsUtils.calcPentadAverages(inWks, outWks, funcs, filenames)
        elif process['interval'] == 'dekad':
            print "Processing CHIRPS dekad data"
            chirpsUtils.calcDekadAverages(inWks, outWks, funcs, filenames)
        elif process['interval'] == 'dekad_range':
            print "Processing CHIRPS dekad data for custom date range"
            startDate = []
            endDate = []
            if 'start_dekad_month' in process:
                startDate = process['start_dekad_month']
            if 'end_dekad_month' in process:
                endDate = process['end_dekad_month']
            years = []
            if 'years_between' in process:
                years = process['years_between']
            chirpsUtils.calcLongTermAverage_Dekad_Dates(inWks, outWks, startDate, endDate, years, funcs, filenames)
    elif process['type'] == 'accumulation':
        if process['interval'] == 'dekad_range':
            print "Processing CHIRPS dekad data for custom date range"
            start = []
            end = []
            if 'start_dekad_month_year' in process:
                st = process['start_dekad_month_year']
                start = [int(st[0]), int(st[1]), int(st[2])]
            else:
                print "Error: start_dekad_month_year is missing"
                raise
            if 'end_dekad_month_year' in process:
                e = process['end_dekad_month_year']
                end = [int(e[0]), int(e[1]), int(e[2])]
            else:
                print "Error: start_dekad_month_year is missing"
                raise
            chirpsUtils.calcDekadAccumulation_Dates(inWks, outWks, start, end, filenames)
    elif process['type'] == 'daily':
        print "Processing CHIRPS daily data"
        threshold = cfg['CHIRPS']['thresholds']['precipitation_threshold']
        ndays = cfg['CHIRPS']['thresholds']['max_days_to_process']
        chirpsUtils.calcDailyStatistics(inWks, outWks, temp_path, funcs, date(2015,06,30), filenames, filenames, threshold, ndays)
    elif process['type'] == 'download':
        if process['interval'] == 'monthly':
            print "Downloading CHIRPS monthly data"
            try:
                dates = process['dates']
            except Exception, e:
                dates = ""
            # if 'start_date' in process:
            #     startDate = process['start_date']
            # else:
            #     startDate = None
            # if 'end_date' in process:
            #     endDate = process['end_date']
            # else:
            #     endDate = None
            chirpsUtils.downloadMonthlyDataFromFTP(outWks, dates)
        elif process['interval'] == 'seasonal':
            try:
                dates = process['dates']
            except Exception, e:
                dates = ""
            print "Downloading CHIRPS seasonal data"
            chirpsUtils.downloadSeasonalDataFromFTP(outWks, dates)
        elif process['interval'] == 'pentad':
            print "Downloading CHIRPS pentad data"

        elif process['interval'] == 'dekad':
            try:
                dates = process['dates']
            except Exception, e:
                dates = ""
            print "Downloading CHIRPS dekad data"
            chirpsUtils.downloadDekadDataFromFTP(outWks, dates)
        elif process['interval'] == 'daily':
            try:
                dates = process['dates']
            except Exception, e:
                dates = ""
            print "Downloading CHIRPS daily data"
            chirpsUtils.downloadDailyDataFromFTP(outWks, dates)



    elif process['type'] == 'crop':
        print "Cropping raster to boundary"
        if 'input_file' in process:
            inFile = process['input_file']
        else:
            inFile = None
        if 'output_file' in process:
            outFile = process['output_file']
        else:
            outFile = None
        if 'boundary_file' in process:
            shpfile = process['boundary_file']
        else:
            shpfile = None
        if inFile and outFile and shpfile:
            if os.path.splitext(inFile)[1] == '.gz':
                # need to unzip file first
                inFile = directoryUtils.unzipFile(inFile)
            gdal_path = cfg['directory']['GDAL']
            rasterUtils.clipRasterToShp(shpfile, inFile, outFile, gdal_path)
    return 0

def processTEMP(process, cfg):
    inWks = process['input_dir']
    outWks = process['output_dir']
    arcpy.env.workspace = inWks
    funcs = process['functions']
    filenames = (process['input_prefix'], process['input_ext'])
    if not funcs:
        funcs = ['MIN', 'MAX']
    modisUtils.calcLongTermAverageTemp(inWks, outWks, funcs, filenames)
    return 0

def processNDVI(process, cfg):
    print 'Calculate NDVI Long Term Averages'
    inWks = process['input_dir']
    outWks = process['output_dir']
    arcpy.env.workspace = inWks
    if 'functions' in process:
        funcs = process['functions']
    else:
        funcs = ['AVG, MIN, MAX']
    if 'EVI' in cfg and 'filenames' in cfg['EVI'] and 'prefix' in cfg['EVI']['filenames']:
        out_prefix = cfg['EVI']['filenames']['prefix']
    if 'EVI' in cfg and 'filenames' in cfg['EVI'] and 'extension' in cfg['EVI']['filenames']:
        out_ext = cfg['EVI']['filenames']['extension']
    if 'output_prefix' in process:
        out_prefix = process['output_prefix']
    if 'output_ext' in process:
        out_ext = process['output_ext']
    filenames = (out_prefix, out_ext)

    ndviUtils.calcLongTermAverageNDVI(inWks, outWks, funcs, filenames)
    return 0

def processEVI(process, cfg):
    print 'Calculate EVI Long Term Averages'
    inWks = process['input_dir']
    outWks = process['output_dir']
    arcpy.env.workspace = inWks
    if 'interval' in process:
        interval = process['interval']
    else:
        interval = 'MONTHLY'
    if 'functions' in process:
        funcs = process['functions']
    else:
        funcs = ['AVG, MIN, MAX']
    if 'EVI' in cfg and 'filenames' in cfg['EVI'] and 'prefix' in cfg['EVI']['filenames']:
        out_prefix = cfg['EVI']['filenames']['prefix']
    if 'EVI' in cfg and 'filenames' in cfg['EVI'] and 'extension' in cfg['EVI']['filenames']:
        out_ext = cfg['EVI']['filenames']['extension']
    if 'output_prefix' in process:
        out_prefix = process['output_prefix']
    if 'output_ext' in process:
        out_ext = process['output_ext']
    filenames = (out_prefix, out_ext)

    if interval == 'MONTHLY':
        eviUtils.calcMonthlyLongTermAverageEVI(inWks, outWks, funcs, filenames)
    else:
        eviUtils.calcLongTermAverageEVI(inWks, outWks, funcs, filenames)
    return 0

def processMODIS(process, cfg):
    if process['type'] == 'mosaic':
        logger.debug("Mosaic MODIS data")
        inWks = process['input_dir']
        outWks = process['output_dir']
        toolDir = None