#!/usr/bin/env python
import os, sys, shutil, re
import datetime as dt
import multiprocessing as mp
import gdal, ogr, osr

gisbase = os.environ['GISBASE'] = r'C:\\Program Files\\GRASS GIS 7.2.1\\'
gisdbase = r'C:\data\grass'
gisaddon = os.environ['GRASS_ADDON_PATH'] = r'C:\Users\*****\AppData\Roaming\GRASS7\addons\scripts\\'
sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "python"))

# import grass scripts
import grass.script as grass
import grass.script.setup as gsetup

# days of the year to model in r.sun
days = []
day1 = dt.datetime(2015, 1, 15).timetuple().tm_yday
days.append(day1)
day2 = dt.datetime(2015, 2, 14).timetuple().tm_yday
days.append(day2)
day3 = dt.datetime(2015, 3, 15).timetuple().tm_yday
days.append(day3)
day4 = dt.datetime(2015, 4, 15).timetuple().tm_yday
days.append(day4)
day5 = dt.datetime(2015, 5, 15).timetuple().tm_yday
days.append(day5)
day6 = dt.datetime(2015, 6, 15).timetuple().tm_yday
days.append(day6)
day7 = dt.datetime(2015, 7, 15).timetuple().tm_yday
days.append(day7)
day8 = dt.datetime(2015, 8, 15).timetuple().tm_yday
days.append(day8)
day9 = dt.datetime(2015, 9, 15).timetuple().tm_yday
days.append(day9)
day10 = dt.datetime(2015, 10, 15).timetuple().tm_yday
days.append(day10)
day11 = dt.datetime(2015, 11, 15).timetuple().tm_yday
days.append(day11)
day12 = dt.datetime(2015, 12, 15).timetuple().tm_yday
days.append(day12)

# sample area
sampleList1 = ['lavbebygNet_024359']
clusterList = []
clusterList.append(sampleList1)


# open log file
global lf
tlog = dt.datetime.strftime(dt.datetime.now(),"%Y-%m-%d_h%Hm%M")
lf = open('rsun_'+tlog+'.log', 'w')

# parameters
location = 'Denmark'
mhorizon = 'Solar'
maxDistance = '500'
hstep = 15
distance = '1.0'

def worker_rsun(vectorId,dayStart,dayEnd):
        # setup grass environment, including temporary mapset
        mtemp = 'temp'+str(1).zfill(2)
        gsetup.init(gisbase, gisdbase, location, mtemp)
        grass.run_command("g.region",vector = vectorId +"@Solar", res='0.4')

        # map names
        prefsun = vectorId+'_glob'
        demh = vectorId+'@Solar'
        horizonBase = vectorId+'hor'
        aspectIn = vectorId+'aspect'+'@Solar'
        slopeIn = vectorId+'slope'+'@Solar'

        # run r.horizon for one azimuth angle
        dayStart = dayStart
        dayEnd = dayEnd
        grass.run_command("r.sun.daily", elevation=demh, \
                          start_day=dayStart, end_day=dayEnd, aspect=aspectIn, \
                          slope=slopeIn, horizon_basename=horizonBase, \
                          horizon_step=15, day_step=1, glob_rad_basename=prefsun, \
                          nprocs=4, overwrite=True)
        
def create_temp():
        global temp
        # create temporary matsets
        gsetup.init(gisbase, gisdbase, location, 'PERMANENT')
        temp = 'temp'+str(1).zfill(2)
        temp_path = gisdbase+'/'+location+'/'+temp
        if os.path.exists(temp_path) == False:
                grass.run_command("g.mapset", flags="c", mapset = temp, quiet = 1)
                printout(temp+' mapset created.')
        else:
                printout(temp+' mapset already exists. skipping...')

def remove_temp():
        # setup is in the target mapset, not temp mapsets
        gsetup.init(gisbase, gisdbase, location, mhorizon)

        # delete the temp mapset
        mapset_temp = 'temp'+str(1).zfill(2)
        grass.run_command("g.mapsets", mapset=mapset_temp, operation = 'remove')
        temp_path = gisdbase+'/'+location+'/'+mapset_temp
        shutil.rmtree(temp_path)

def copy_mapset(mapset_from,mapset_to,vectorId):
        # list contents of temp mapset
        grass.run_command("g.mapset", mapset=mapset_from, quiet=1)
        raster_list = grass.list_strings('rast', pattern=vectorId+'_glob')
        # switch to target mapset and copy rasters over
        grass.run_command("g.mapset", mapset=mapset_to,quiet=1)
        for rast in raster_list:
                cmd = rast+'@Solar'+','+rast
                grass.run_command("g.copy", rast=cmd, overwrite=True)

def printout(str_text):
        timestamp = dt.datetime.strftime(dt.datetime.now(),"%H:%M:%S")
        lf.write(timestamp+": "+str_text+'\n')
        print timestamp+": "+str_text

def main():
        printout("STARTING R.SUN")
        # start logging        
        start = dt.datetime.now()
        starttime = dt.datetime.strftime(start,"%m-%d %H:%M:%S")
        printout('START  r.sun.daily '+ starttime)

        # create one temp directory for each CPU core
        printout('Creating temporary mapset')
        create_temp()

        # copy horizon maps to temp mapset:
        grass.run_command("g.mapset", mapset=mhorizon, quiet=1)
        horizonList = grass.list_strings('rast', pattern='lavbebygNet_0'+'24359'+'hor*')
        horizonList = ''.join(horizonList)
        horizonList = str.split(horizonList, '@Solar')
        horizonList.pop()
        grass.run_command("g.mapset", mapset=temp, quiet=1)
        for rast in horizonList:
                cmd = rast+'@Solar'+','+rast
                grass.run_command('g.copy', raster=cmd, overwrite=True)

        # return to base mapset
        grass.run_command('g.mapset', mapset=mhorizon, quiet=1)

        # start horizon map calculations 
        process = 1
        for i in clusterList:
                for sample in i:
                        global vectorId
                        vectorId = sample
                        jobs = []
                        proc = 0
                        iter = 0
                        dayN = 0
                        while iter < 13:
                                if proc <= process:
                                        global dayStart
                                        dayStart = days[dayN]
                                        dayEnd = dayStart + 1
                                        p = mp.Process(target=worker_rsun, args=(vectorId, dayStart, dayEnd))
                                        p.start()
                                        jobs.append(p)
                                        pid = str(p.pid)
                                        proc += 1
                                        iter += 1
                                        dayN += 1
                                else:
                                        # wait for all the Processes to finish
                                        proc = 1
                                        if iter == 12:
                                                iter += 1
                                        for p in jobs:
                                                pid = str(p.pid)
                                                p.join()
                        printout("R.sun finished for "+vectorId)
                        grass.run_command("g.mapset", mapset=temp, quiet=1)
                        grass.run_command("g.region",vector = vectorId +"@Solar", res='0.4')
                        cmd = "%s = %s + %s + %s + %s + %s + %s + %s + %s + %s + %s + %s + %s" % (vectorId+'_glob', vectorId+'_glob'+'_015'+'@temp01', vectorId+'_glob'+'_045'+'@temp01', vectorId+'_glob'+'_074'+'@temp01', vectorId+'_glob'+'_105'+'@temp01', vectorId+'_glob'+'_135'+'@temp01', vectorId+'_glob'+'_166'+'@temp01', vectorId+'_glob'+'_196'+'@temp01', vectorId+'_glob'+'_227'+'@temp01', vectorId+'_glob'+'_258'+'@temp01', vectorId+'_glob'+'_288'+'@temp01', vectorId+'_glob'+'_319'+'@temp01', vectorId+'_glob'+'_349'+'@temp01')
                        grass.mapcalc(cmd, overwrite = True)

                        # copy all the files to horizon mapset 
                        printout("R.sun finished. copying files back to "+mhorizon)
                        mtemp = 'temp'+str(1).zfill(2)
                        copy_mapset(mtemp, mhorizon, vectorId)



        # delete the temp mapsets
        #printout("Removing temporary mapsets")
        #remove_temp()

        # stop logging and record total processing time.
        end = dt.datetime.now()
        endtime = dt.datetime.strftime(end,"%m-%d %H:%M:%S")
        processingtime = end - start
        printout('END r.horizon, processing time: '+str(processingtime))
        lf.close()
        sys.exit("Finished")



if __name__ == "__main__":
        #options, flags = grass.parser()
        main()
