#!/bin/bash
SOURCE="$0"
source /usr/lib/elive-tools/functions
#EL_REPORTS="1"
#el_make_environment

main(){
    # pre {{{
    local data is_data_valid ip

    if ! el_dependencies_check curl ; then
        if ! el_dependencies_install curl ; then
            exit 1
        fi
    fi

    if ! el_verify_internet ; then
        el_error "no internet connection found"
        exit 1
    fi

    if [[ -n "$1" ]] ; then
        if echo "$1" | grep -qs "^[[:digit:]]*" ; then
            ip="$1"
        fi
    fi


    # }}}
    # DEMO outputs {{{

    #  api.ipaddresslabs.com:

    #<?xml version="1.0" encoding="UTF-8"?>
    #<response>
        #<query_status>
            #<query_status_code>OK</query_status_code>
            #<query_status_description>Query successfully performed.</query_status_description>
        #</query_status>
        #<ip_address>88.0.190.30</ip_address>
        #<geolocation_data>
            #<continent_code>EU</continent_code>
            #<continent_name>Europe</continent_name>
            #<country_code_iso3166alpha2>ES</country_code_iso3166alpha2>
            #<country_code_iso3166alpha3>ESP</country_code_iso3166alpha3>
            #<country_code_iso3166numeric>724</country_code_iso3166numeric>
            #<country_code_fips10-4>SP</country_code_fips10-4>
            #<country_name>Spain</country_name>
            #<region_code>SP52</region_code>
            #<region_name>Aragon</region_name>
            #<city>Zaragoza</city>
            #<postal_code>-</postal_code>
            #<metro_code>-</metro_code>
            #<area_code>-</area_code>
            #<latitude>41.6453</latitude>
            #<longitude>-0.8849</longitude>
            #<isp>Telefonica de Espana</isp>
            #<organization>Telefonica de Espana</organization>
        #</geolocation_data>
    #</response>

    #########################################


    #  freegeoip.net:
    #<Response>
        #<Ip>88.0.190.30</Ip>
        #<CountryCode>ES</CountryCode>
        #<CountryName>Spain</CountryName>
        #<RegionCode>52</RegionCode>
        #<RegionName>Aragon</RegionName>
        #<City>Zaragoza</City>
        #<ZipCode></ZipCode>
        #<Latitude>41.6453</Latitude>
        #<Longitude>-0.8849</Longitude>
        #<MetroCode></MetroCode>
        #<AreaCode></AreaCode>
    #</Response>



    # - DEMO outputs }}}

    # OTHER services (json only):
    #curl https://ipinfo.io/json
    #curl https://api.ipdata.co?api-key=test
    #curl ipgeolocation.com

    # try with ipapi (fast)
    if ! ((is_data_valid)) ; then
        if [[ -n "$ip" ]] ; then
            data="$( curl -L -s --max-time 12 -A "Mozilla" "http://ip-api.com/xml/$ip" )"
        else
            data="$( curl -L -s --max-time 12 -A "Mozilla" "http://ip-api.com/xml/" )"
        fi

        # verify
        if [[ -n "$data" ]] && \
            { [[ "$data" = *atitude* ]] || [[ "$data" = *"<lat>"* ]] ; } && \
            { [[ "$data" = *"ountryCode"* ]] || [[ "$data" = *"ountrycode"* ]] ; } ; then
            is_data_valid=1
            el_debug "using ip-api:\n$data"
        else
            el_debug "FAILED using ip-api"
        fi
    fi


    # try with geoplugin (fast)
    if ! ((is_data_valid)) ; then
        if [[ -n "$ip" ]] ; then
            data="$( curl -L -s --max-time 12 -A "Mozilla" "http://www.geoplugin.net/xml.gp?ip=$ip" )"
        else
            data="$( curl -L -s --max-time 12 -A "Mozilla" "http://www.geoplugin.net/xml.gp" )"
        fi

        # verify
        if [[ -n "$data" ]] && \
            { [[ "$data" = *atitude* ]] || [[ "$data" = *"<lat>"* ]] ; } && \
            { [[ "$data" = *"ountryCode"* ]] || [[ "$data" = *"ountrycode"* ]] ; } ; then
            is_data_valid=1
            el_debug "using geoplugin:\n$data"
        else
            el_debug "FAILED using geoplugin"
        fi
    fi

    # try with ipapi (fast)
    if ! ((is_data_valid)) ; then
        if [[ -n "$ip" ]] ; then
            data="$( curl -L -s --max-time 12 -A "Mozilla" "https://ipapi.co/$ip/xml/" )"
        else
            data="$( curl -L -s --max-time 12 -A "Mozilla" "https://ipapi.co/xml/" )"
        fi

        # verify
        if [[ -n "$data" ]] && \
            { [[ "$data" = *atitude* ]] || [[ "$data" = *"<lat>"* ]] ; } && \
            { [[ "$data" = *"ountryCode"* ]] || [[ "$data" = *"ountrycode"* ]] ; } ; then
            is_data_valid=1
            el_debug "using ipapi.co:\n$data"
        else
            el_debug "FAILED using ipapi.co"
        fi
    fi

    # try with freegeoip (good but slow, reliable, which is more important)
    # note: ip can be empty, this will make things faster by not fetching it first
    if ! ((is_data_valid)) ; then
        if [[ -n "$ip" ]] ; then
            data="$( curl -L -s --max-time 12 -A "Mozilla" "https://freegeoip.app/xml/$ip" )"
        else
            data="$( curl -L -s --max-time 12 -A "Mozilla" "https://freegeoip.app/xml/" )"
        fi


        ## verify
        if [[ -n "$data" ]] && \
            { [[ "$data" = *atitude* ]] || [[ "$data" = *"<lat>"* ]] ; } && \
            { [[ "$data" = *"ountryCode"* ]] || [[ "$data" = *"ountrycode"* ]] ; } ; then
            is_data_valid=1
            el_debug "using freegeoip.app:\n$data"
        else
            el_debug "FAILED using freegeoip.app"
        fi
    fi



    # since this point, we need to have an ip for fetch data
    #if ! ((is_data_valid)) && [[ -z "$ip" ]] ; then
        #ip="$( showmyip )"
    #fi

    ## try with ipaddresslabs:
    ## note: actually it says demo license expired, place this test at the end
    ## note: it probably works without ip too, but the demo license has been removed
    #if ! ((is_data_valid)) ; then
        #data="$( curl -L -s --max-time 12 -A "Mozilla" "http://api.ipaddresslabs.com/iplocation/v1.7/locateip?key=demo&ip=${ip}&format=XML" )"

        ## verify
        #if [[ -n "$data" ]] && [[ "$data" = *atitude* ]] ; then
            #is_data_valid=1
        #fi
    #fi


    if ((is_data_valid)) ; then
        # show the ip, always good to have
        if [[ -n "$ip" ]] ; then
            echo "ip::$ip"
        fi

        # disable case sensitive matchings:
        shopt -s nocasematch

        while read -ru 3 line
        do
            # filter/remove some useless stuff
            line="${line//geoplugin_/}"

            el_debug "parsing $line"

            case "$line" in
                \<latitude\>*|\<lat\>*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "latitude::$line"
                    ;;
                \<longitude\>*|\<lon\>*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "longitude::$line"
                    ;;
                \<continentcode*|\<continent_code*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "continent_code::$line"
                    ;;
                \<continentname*|\<continent_name*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "continent_name::$line"
                    ;;
                \<countrycode*|\<country_code*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "country_code::$line"
                    ;;
                \<countryname*|\<country_name*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "country_name::$line"
                    is_get_countryname=1
                    ;;
                \<regionname*|\<region_name*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "region_name::$line"
                    ;;
                \<regioncode*|\<region_code*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "region_name::$line"
                    ;;
                \<city\>*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "city_name::$line"
                    ;;
                \<isp\>*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "isp_provider_name::$line"
                    ;;
                \<zip\>*|\<zipcode\>*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "zip_code::$line"
                    ;;
                \<timezone\>*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "timezone::$line"
                    ;;
                \<ip\>*)
                    line="${line%</*>}"
                    line="${line#<*>}"

                    echo "ip::$line"
                    ;;
                \<Country\>*)
                    # special cases:
                    if ! ((is_get_countryname)) ; then
                        line="${line%</*>}"
                        line="${line#<*>}"

                        echo "country_name::$line"
                    fi
                    ;;
                *"xml version"*|\<org\>*|\<*query\>*|\<status\>*|\<region\>*|\<as\>*|\<*geoPlugin\>*|\<request\>*|\<credit\>*|\<delay\>*|\<*areaCode\>*|\<*dmaCode\>*|\<inEU\>*|\<*VATrate\>*|\<locationaccuracyradius\>*|\<currency*|\<*response\>*|\<metrocode\>*)
                    # ignore these values
                    continue
                    ;;
                *)
                    #simple reports:
                    if [[ "$EL_DEBUG" -gt 2 ]] ; then
                        NOREPORTS=1 el_warning "unknown value: $line"
                    fi
                    ;;
            esac
        done 3<<< "$( echo "$data" | sed -e 's|></|> </|g' -e 's|><|>\n<|g' )" | sort -u
    fi

}

#
#  MAIN
#
main "$@"

# vim: set foldmethod=marker :
