#!/usr/bin/env python3
# system modules
import argparse
import textwrap
import logging
import os
import json
import sys

# internal modules
import patatmo
from patatmo.utils import *
from patatmo.api.client import NetatmoClient
from patatmo.api.authentication import Authentication

# external modules

# Options
parser = argparse.ArgumentParser( 
    description = textwrap.dedent("""
        Issue a Getmeasure request to the Netatmo server and write the results
        to file.
        """)
    )
parser.add_argument("-p","--password", 
    help = "Netatmo developer account password. " 
        "Takes precedence over NETATMO_PASSWORD environment variable", 
    required = False)
parser.add_argument("-u","--user", 
    help = "Netatmo developer account username. "
        "Takes precedence over NETATMO_USERNAME environment variable", 
    required = False)
parser.add_argument("-i","--id", 
    help = "Netatmo app client id. "
        "Takes precedence over NETATMO_CLIENT_ID environment variable", 
    required = False)
parser.add_argument("-s","--secret", 
    help = "Netatmo app client secret. "
        "Takes precedence over NETATMO_CLIENT_SECRET environment variable", 
    required = False)
parser.add_argument("-o","--output", 
    help = "output file. Defaults to '-' which means STDOUT.", default = "-")
parser.add_argument("-f","--tmpfile", help = "temporary authentication file",
    required = False)
parser.add_argument("-v","--verbose", help = "verbose output",
    action="store_true", default = False)

# Getmeasure arguments
parser.add_argument("-d","--device", help = "mac address of the device", 
    required = True)
parser.add_argument("-m","--module", help = "The mac address of the module of "
    "interest. If not specified, returns data of the device. If "
    "specified, returns data from the specified module", required = False)
parser.add_argument("-b","--begin", help = "UNIX-timestamp of " 
    "first measure to receive. Limit is 1024 measures.", required = False)
parser.add_argument("-e","--end", help = "UNIX-timestamp of " 
    "last measure to receive. Limit is 1024 measures.", required = False)
parser.add_argument("-t","--type", help = "Measures interested in. "
        "List of 'rain','humidity','pressure','wind' and 'temperature'", 
        type = list, required = False)
parser.add_argument("-c","--scale", help = "Timelapse between two measurements."
    "'max' (every value is returned), '30min' (1 value every 30min), "
    "'1hour', '3hours', '1day', '1week', '1month'. Defaults to 'max'.",
    required = False)
parser.add_argument("--optimize", action="store_true", default=False,
    help = "Determines the format of the answer.  Default is False. For mobile " 
    "apps we recommend True and False if bandwidth isn't an issue as " 
    "it is easier to parse.", )
parser.add_argument("--real_time", help = "If scale different than max, " 
    "timestamps are by default offset + scale/2. To get exact timestamps, use "
    "true. Default is false.", action="store_true", default = False
    )
parser.add_argument("-r","--raw", help = "Return the raw API output.", 
    action="store_true", default = False
    )


args = parser.parse_args()

if not args.user: # no user given via command-line
    NETATMO_USERNAME = os.environ.get("NETATMO_USERNAME")
    assert NETATMO_USERNAME, ("Specify Netatmo developer account username " 
        "via --user argument or NETATMO_USERNAME environment variable.")
else:
    NETATMO_USERNAME = args.user
if not args.password: # no password given via command-line
    NETATMO_PASSWORD = os.environ.get("NETATMO_PASSWORD")
    assert NETATMO_PASSWORD, ("Specify Netatmo developer account password " 
        "via --password argument or NETATMO_PASSWORD environment variable.")
else:
    NETATMO_PASSWORD = args.password
if not args.id: # no id given via command-line
    NETATMO_CLIENT_ID = os.environ.get("NETATMO_CLIENT_ID")
    assert NETATMO_CLIENT_ID, ("Specify Netatmo app client id " 
        "via --id argument or NETATMO_CLIENT_ID environment variable.")
else:
    NETATMO_CLIENT_ID = args.id
if not args.secret: # no user given via command-line
    NETATMO_CLIENT_SECRET = os.environ.get("NETATMO_CLIENT_SECRET")
    assert NETATMO_CLIENT_SECRET, ("Specify Netatmo app client secret " 
        "via --secret argument or NETATMO_CLIENT_SECRET environment variable.")
else:
    NETATMO_CLIENT_SECRET = args.secret

if args.output == "-" or not args.output:
    OUTPUT_FILE = sys.stdout
else:
    OUTPUT_FILE = open(args.output,"w")

if args.verbose:
    logging.basicConfig(level = logging.DEBUG)
else:
    logging.basicConfig(level = logging.WARNING)

# read credentials
CREDENTIALS = {
    "username":NETATMO_USERNAME,
    "password":NETATMO_PASSWORD,
    "client_id":NETATMO_CLIENT_ID,
    "client_secret":NETATMO_CLIENT_SECRET,
    }

# set up a client
client = NetatmoClient(
    authentication = Authentication(
        credentials = CREDENTIALS,
        tmpfile = args.tmpfile,
        ),
    )

# issue the Getmeasure request
logging.info("Issuing Getmeasure request...")
response = client.Getmeasure( 
    date_begin = args.begin,
    date_end   = args.end,
    device_id  = args.device,
    module_id  = args.module,
    type       = args.type,
    scale      = args.scale,
    real_time  = args.real_time,
    optimize   = args.optimize,
    )
logging.info("Getmeasure request completed!")

if args.raw:
    logging.info("Using raw API response as output")
    OUTPUT_STRING = json.dumps(response.response,sort_keys=True,indent=4)
else:
    # convert response
    logging.info("Converting Getmeasure response...")
    dataframe = response.dataframe()
    logging.info("Getmeasure response converted!")

    OUTPUT_STRING = dataframe.to_csv()

# output
logging.info("Writing to output file '{}'...".format(OUTPUT_FILE.name))
OUTPUT_FILE.write(OUTPUT_STRING)
logging.info("Written to output file!")
