#!/bin/sh

############################################################################
#
# MODULE:       r.in.wms for GRASS 6
# AUTHOR(S):    Cedric Shock (cedricgrass AT shockfamily.net)
# PURPOSE:      To import data from web mapping servers
# COPYRIGHT:    (C) 2006 by Cedric Shock
#
#               This program is free software under the GNU General Public
#               License (>=v2). Read the file COPYING that comes with GRASS
#               for details.
#
#############################################################################

#%Module
#%  description: Downloads and imports data from WMS servers
#%  keywords: wms
#%End
#%flag
#% key: l
#% description: List available layers and exit
#% guisection: Request
#%end
#%flag
#% key: d
#% description: Skip to downloading (to resume downloads faster)
#% guisection: Download
#%end
#%flag
#% key: o
#% description: Don't request transparent data.
#% guisection: Request
#%end
#%flag
#% key: c
#% description: Clean existing data out of download directory.
#% guisection: Download
#%end
#%flag
#% key: k
#% description: Keep band numbers instead of using band color names.
#% guisection: Import
#%end
#%flag
#% key: p
#% description: Don't reproject the data, just patch it.
#% guisection: Import
#%end
#%option
#% key: output
#% type: string
#% description: Name for resultant raster map
#% gisprompt: new,cell,raster
#% required : no
#% guisection: Import
#%end
#%option
#% key: mapserver
#% type: string
#% description: Mapserver to request data from
#% required: yes
#% guisection: Request
#%end
#%option
#% key: layers
#% type: string
#% description: Layers to request from map server
#% multiple: yes
#% required: no
#% guisection: Request
#%end
#%option
#% key: styles
#% type: string
#% description: Styles to request from map server
#% multiple: yes
#% required: no
#% guisection: Request
#%end
#%option
#% key: srs
#% type: string
#% description: Source projection to request from server
#% answer:EPSG:4326
#% guisection: Request
#%end
#%option
#% key: format
#% type: string
#% description: Image format requested from the server
#% options: geotiff,tiff,jpeg,gif,png
#% answer: geotiff
#% required: yes
#% guisection: Request
#%end
#%option
#% key: wmsquery
#% type:string
#% description: Addition query options for server
#% answer: version=1.1.1
#% guisection: Request
#%end
#%option
#% key: maxcols
#% type: integer
#% description: Maximum columns to request at a time
#% answer: 1024
#% required : yes
#% guisection: Request
#%end
#%option
#% key: maxrows
#% type: integer
#% description: Maximum rows to request at a time
#% answer: 1024
#% required : yes
#% guisection: Request
#%end
#%option
#% key: tileoptions
#% type: string
#% description: Additional options for r.tileset
#% required : no
#% guisection: Request
#%end
#%option
#% key: region
#% type: string
#% description: Named region to request data for. Current region used if omitted.
#% required : no
#% guisection: Request
#%end
#%option
#% key: folder
#% type: string
#% description: Folder to save downloaded data to
#% required : no
#% guisection: Download
#%end
#%option
#% key: wgetoptions
#% type: string
#% description: Additional options for wget
#% answer: -c -t 5 --user-agent=MSIE5.5 
#% required : no
#% guisection: Download
#%end
#%option
#% key: method
#% type: string
#% description: Reprojection method to use
#% options:nearest,bilinear,cubic,cubicspline
#% answer:nearest
#% required: yes
#% guisection: Import
#%end
#%option
#% key: v
#% type: integer
#% description: Verbosity level
#% answer: 1
#%end

if  [ -z "$GISBASE" ] ; then
    echo "You must be in GRASS GIS to run this program." 1>&2
 exit 1
fi

if [ "$1" != "@ARGS_PARSED@" ] ; then
  exec g.parser "$0" "$@"
fi

#### setup temporary file
TMP="`g.tempfile pid=$$`"
if [ $? -ne 0 ] || [ -z "$TMP" ] ; then
    echo "ERROR: unable to create temporary files" 1>&2
    exit 1
fi

# check if we have wget
if [ ! -x "`which wget`" ] ; then
    echo "wget is required, please install it first" 1>&2
    exit 1
fi

# check if we have bc -> used in wms.request and wms.download
if [ ! -x "`which bc`" ] ; then
    echo "bc is required, please install it first" 1>&2
    exit 1
fi

# check if we have sed
if [ ! -x "`which sed`" ] ; then
    echo "sed is required, please install it first" 1>&2
    exit 1
fi

# check if we have gdalwarp -> used in r.in.gdalwarp
if [ $GIS_FLAG_P -ne 1 ] ; then
    if [ ! -x "`which gdalwarp`" ] ; then
        echo "gdalwarp is required, please install it first" 1>&2
        exit 1
    fi
fi

# Remember the intial field seperator
defaultIFS="$IFS"

# Remember the previous path
prevPATH="$PATH"
PATH="$PATH:${GISBASE}/etc/r.in.wms/"
export PATH

#####################
# name:     message
# purpose:  displays messages to the user
# usage: message level text

message () {
	if [ $1 -lt $GIS_OPT_V ] ; then
		shift
		echo "$@"  
	fi
}

#######################################################################
# name:     exitprocedure
# purpose:  removes all temporary files
#
exitprocedure()
{
	message 0 "User break!"
	PATH=$prevPATH
	export PATH
	rm -f "${TMP}"*
	exit 1
}
trap "exitprocedure" 2 3 15

BC="bc"
BCARGS="-l"

#######################################################################
# name:     addargument
# purpose:  make arguments for a sub command
#
addargument() {
	if [ -z "$3" ] ; then
		message 1 "Skipping argument for $2"
 	else
		eval "$1=\"\$$1 '$2=$3'\""
	fi
}

#######################################################################
# name:     addflag
# purpose:  make arguments for a sub command
#
addflag() {
	if [ $3 -eq 1 ] ; then
		eval "$1=\"\$$1 -$2\""
	fi
}

#####################3
# name: calculate
# purpose: perform calculations
# usage: varname "expr"

calculate() {
	message 3 "$2"
	c_tmp=`echo "$2" | $BC $BCARGS`
	eval $1=$c_tmp
}


######################
# name: listLayers
# purpose: list layers available from this server

listLayers() {

	CAPABILITIES_FILE="${TMP}capabilities.xml"
    
	STRING="service=WMS&request=GetCapabilities&${GIS_OPT_WMSQUERY}";

	### wget the XML and grep the lines with layer names
	echo "List of layers for server ${GIS_OPT_MAPSERVER}:"
	wget ${GIS_OPT_WGETOPTIONS} --post-data=${STRING} $GIS_OPT_MAPSERVER -O $CAPABILITIES_FILE;
	message 1 wget ${GIS_OPT_WGETOPTIONS} --post-data=${STRING} $GIS_OPT_MAPSERVER -O $CAPABILITIES_FILE;

	# use xml2
	if [ -x "`which xml2`" ] ; then
		cat $CAPABILITIES_FILE | xml2 | \
		grep "Layer/SRS=\|Layer/Name=\|Layer/Title=\|Style/Name=\|Style/Title=\|Layer/Abstract=" | \
		sed -e          "s/.*Layer\\/Name=/LAYER: /" | \
		sed -e           "s/.*Layer\\/SRS=/  SRS: /" | \
 		sed -e         "s/.*Layer\\/Title=/  Title: /" | \
		sed -e      "s/.*Layer\\/Abstract=/  |/" | \
		sed -e  "s/.*Layer\\/Style\\/Name=/  STYLE: /" | \
		sed -e "s/.*Layer\\/Style\\/Title=/    Style title: /" \
		  > "${TMP}capabilities.txt"

	else : # xml2 is not available
		echo "Note: xml2 NOT avaliable"
		cat $CAPABILITIES_FILE | \
		grep "Name\|Title\|Style\|Layer" | \
		sed -e "s/<Layer .*>/LAYER:/"| \
		sed -e "s/<\/Layer.*>//"| \
		sed -e "s/<Name>\s*\(\w*\)/~\1~/g" | \
		sed -e "s/<\/Name>\n//g" | \
		sed -e "s/<Style>\n*\s*\(\w*\)/Style: \1/" |\
		sed -e "s/<\/Style>//" |\
		sed -e "s/<Title>\(.*\)<\/Title>/\t --\1 /" | \
		sed -e "s/<\/Title>//" | \
		sed -e "s/<\/*.*\/*\/*>//" \
		  > "${TMP}capabilities.txt"
	fi

	if [ `wc -l < "${TMP}capabilities.txt"` -eq 0 ] ; then
	    echo
	    echo "ERROR: Parsing XML file"
	    echo "------------------------"
	    cat "$CAPABILITIES_FILE"
	else
	    cat "${TMP}capabilities.txt"
	fi


	if [ -e $CAPABILITIES_FILE ] ; then
	    rm -f "$CAPABILITIES_FILE" "${TMP}capabilities.txt" "$TMP"
        fi
        exit 1;
}


#### Test for listing layers

if [ $GIS_FLAG_L -eq 1 ] ; then
	listLayers
fi

#### Exit if there is no map
# It would be a good idea to test if the map already exists here too

if [ -z "${GIS_OPT_OUTPUT}" ] ; then
	echo "No output map specified" 1>&2
	exit 1;
fi

REQUEST=""
DOWNLOAD=""
GDALWARP=""

eval `g.gisenv`

#Job number one: pick a folder
if [ -z "${GIS_OPT_FOLDER}" ] ; then
	GIS_OPT_FOLDER=${GISDBASE}/wms_download
fi

PREFIX=${GIS_OPT_OUTPUT}
REQUESTFILE=${GIS_OPT_FOLDER}/${PREFIX}_${GIS_OPT_REGION}.wget

if [ ! -z "$GIS_OPT_REGION" ] ; then
   eval `g.findfile element=windows file=$GIS_OPT_REGION`
   if [ ! "$file" ] ; then
      echo "Region file '$GIS_OPT_REGION' not found." 1>&2
      exit 1
   fi
fi

addflag REQUEST o ${GIS_FLAG_O}
addflag REQUEST c ${GIS_FLAG_C}
addflag REQUEST p ${GIS_FLAG_P}
addargument REQUEST folder "${GIS_OPT_FOLDER}"
addargument REQUEST prefix ${PREFIX}
addargument REQUEST region ${GIS_OPT_REGION}
addargument REQUEST mapserver ${GIS_OPT_MAPSERVER}
addargument REQUEST layers ${GIS_OPT_LAYERS}
addargument REQUEST styles ${GIS_OPT_STYLES}
addargument REQUEST srs ${GIS_OPT_SRS}
addargument REQUEST format ${GIS_OPT_FORMAT}
addargument REQUEST wmsquery ${GIS_OPT_WMSQUERY}
addargument REQUEST maxcols ${GIS_OPT_MAXCOLS}
addargument REQUEST maxrows ${GIS_OPT_MAXROWS}
addargument REQUEST tileoptions "${GIS_OPT_TILEOPTIONS}"

if [ $GIS_FLAG_D -eq 0 ] ; then
	message 0 "wms.request $REQUEST"
	eval "wms.request $REQUEST"
	if [ $? -ne 0 ] ; then
	   echo "ERROR: wms.request failure" 1>&2
	   exit 1
	fi
fi

addargument DOWNLOAD requestfile "${REQUESTFILE}"
addargument DOWNLOAD wgetoptions "${GIS_OPT_WGETOPTIONS}"

message 0 "wms.download $DOWNLOAD"
eval "wms.download $DOWNLOAD"

# Job 2: make list of files

CONTENTS=`cat "${REQUESTFILE}"`

FILES=""
COUNT=0
for line in $CONTENTS ; do
	eval "$line"
	if [ $COUNT -eq 0 ] ; then
		FILES="$OUTPUT_FILE"
	else
		FILES="$FILES,$OUTPUT_FILE"
	fi
	COUNT=`expr $COUNT + 1`
done

addflag GDALWARP c 1
addflag GDALWARP k ${GIS_FLAG_K}
addflag GDALWARP p ${GIS_FLAG_P}
addargument GDALWARP input "$FILES"
addargument GDALWARP output ${GIS_OPT_OUTPUT}
addargument GDALWARP method ${GIS_OPT_METHOD}
addargument GDALWARP s_srs ${GIS_OPT_SRS}

# check for error like 'Service Exception Report'
if [ `file -b "$FILES" | grep -c "^HTML\|^XML"` -eq 1 ] ; then
  echo "#################################"
  cat "$FILES"
  echo
  rm -f "${TMP}"*
  exit 1
fi

message 0 "r.in.gdalwarp $GDALWARP"
eval "r.in.gdalwarp $GDALWARP"

# Clean up:
rm -f "${TMP}"*

