
/**
 * Created by Robert Pastel on 11/12/2016.
 */
/**
 * Grab gets the http-builder jar from the maven site
 *
 * If you get the error
 *
 *       error groovyc cannot @Grab without Ivy
 *
 * then
 *      1. Download the binary for Ivy at
 *            http://ant.apache.org/ivy/
 *      2. Unzip and extract the jar
 *      3. Put it in a nearby directory
 *      4. Add it as a module to the project by
 *             i. File -> Project structure -> Modules -> Dependencies
 *             ii. Add by clicking on the "+" on the right, select JARs
 *             iii. Navigate to where you put the Ivy jar
 *      Reference
 *        https://intellij-support.jetbrains.com/hc/en-us/community/posts/206913575-Installing-Ivy-plugin-
 */
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7')

import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*

/**
 * Make the post request
 *
 * Note that the HTTPBulider should reference only the site
 * and  the path specifies the path to script.
 * This avoids 403 (Forbidden)
 *
 * Documentation for HTTPBuilder is at
 * https://github.com/jgritman/httpbuilder/wiki
 */
def http = new HTTPBuilder( 'https://forest.moscowfsl.wsu.edu' )
// You can find the post variables and value, by submitting a request from the website
// then inspect -> Networks -> click wd.pl -> Form Data.
// You can even copy and paste from the inspector to your script.
def postBody = [
        me:'' ,
        units:'ft',
        description:'' ,
        climyears:'10',
        Climate:'../climates/al010831',
        achtung:'WEPP run',
        SoilType:'clay',
        UpSlopeType:'OldForest',
        ofe1_top_slope:'0',
        ofe1_length:'50',
        ofe1_pcover:'100',
        ofe1_rock:'20',
        ofe1_mid_slope:'30',
        LowSlopeType:'OldForest',
        ofe2_top_slope:'30',
        ofe2_length:'50',
        ofe2_pcover:'100',
        ofe2_rock:'20',
        ofe2_bot_slope:'5',
        climate_name:'BIRMINGHAM WB AP AL',
        Units:'m',
        actionw:'Run WEPP'
]
// Make the post request and get back the GPath for the html.
// Note the path to the script. It is necessary to split up the URI this way.
def html = http.post(path: '/cgi-bin/fswepp/wd/wd.pl', body: postBody)



// Now get the table of interest results using GPATH
// See http://groovy-lang.org/processing-xml.html#_gpath
def erodeTable = html.BODY.FONT.BLOCKQUOTE.CENTER.P.TABLE
// Note that sometimes the GPath hierarchy is broken,
// but you can always make the depth first searches
/**
 * Map of Maps
 *
 * We want a map like this:
 * analysis[period][variable] -> value
 *
 * also want to make a Map from variables to untis
 *
 * Note that this should work for any value of "years to simulate".
 */
// create the analysis Map
def analysis = [:]

// Gather the keys and make the units map
def i = 0 // counts table rows, so we can do something special for the first table row
def periods = []
def variables = []
def units = [:]
// Note that erodeTable is a GPathResult, so we can search it.
erodeTable."**".findAll{it.name() == "TR"}.each{tr ->
    // The first table row lists the variables with their untis
    if ( i == 0){
        for(j = 0; j < tr.TH.size(); j++){
            // We want to sikp the first header
            if(j > 0){
                String variable_unit = tr.TH[j]
                // Some regular expression to extract variable names and units
                // See http://groovy-lang.org/operators.html#_regular_expression_operators
                // and http://www.regular-expressions.info/
                // Variable names will have only alphabets and units are inside parenthesis
                def m = variable_unit =~ /([A-Za-z]+)\((.+)\)/
                if (m){
                    // Note that the capture groups are Strings
                    variables[j-1] = m[0][1]
                    units.put(variables[j-1], m[0][2])
                }
            }
        }
    }
    // Table rows greater than 0 contains a periods
    else if(i > 0){
        // We will want to use the table header as a key to a map,
        // so we MUST use toString method so that the hashing works properly.
        // Java hashes Objects different from Strings
        periods[i-1] = tr.TH.toString()
    }
    i++
}

//println periods
//println variables
//println units

// Now construct the analysis table from the bottom up
i = 0 // for tracking the periods and table row
erodeTable."**".findAll{it.name() == "TR"}.each{ tr ->
    // construct the period_variable map
    if (i > 0) { // skip the first row because it is a header row
        def j = 0; // for tracking the variables
        def period_variable = [:]
        tr."**".findAll { it.name() == "TD" }.each { td ->
            period_variable.put(variables[j], td)
            j++
        }
        analysis.put(periods[i-1], period_variable) // use i-1 because we skip the first table row
    }
    i++
}
// now we can access the analysis table like this
String period = "Average"
String variable = "Runoff"
println "The ${period} ${variable} is ${analysis[period][variable]} ${units[variable]}"

/**
 *  Find the average annual sediment leaving profile in units t/ha
 *  It is in function showextendedoutput() that is evoked by "WEPP results" link
 *
 *  Note that there is only one occurrence of "t/ha" in the entire response.
 *
 */
def scriptNode = html.HEAD.SCRIPT
// extract the SCRIPT
String script = scriptNode.toString() // Make sure it is a string
// create the variables to save captures from matches
def leavingLine
def leavingValues = []
def leavingUnits = ["t/ha", "ha"]

// Use regular expressions to get line, Note that quotes delineate the line
//def m = script =~ /".+t\/ha.+"/  // this works, but the slash must be escaped
// We can also use groovy strings and then the / is escaped for us
def m = script =~ /".+${leavingUnits[0]}.+"/
if(m){
    // Found it, so clean up the leavingLine. Note the use of regular expressions in the replaceAll
    leavingLine = m[0]
    leavingLine = leavingLine.replaceAll(/ +/, ' ') // remove extra spaces
    leavingLine = leavingLine.replaceAll(/" /,'') // remove leading quote
    leavingLine = leavingLine.replaceAll(/"/,'') // remove remaining quotes

    // Now extract the values
    m = leavingLine =~ /([\d\.]+) ${leavingUnits[0]} \([\w\s]+([\d\.]+) ${leavingUnits[1]}/
    if(m){
        leavingValues[0] = m[0][1]
        leavingValues[1] = m[0][2]
    }
}
// Now we can use our regular expression captures like this
//println leavingLine
println "The average annual sediment leaving is ${leavingValues[0]} ${leavingUnits[0]}"
