#!/usr/bin/python

# Copyright (c) 2013 Paolo Patruno <p.patruno@iperbole.bologna.it>
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
# 1. Redistributions of source code must retain the above copyright notice,
#   this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
# 3. Neither the name of mosquitto nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'rmap.settings'
from django.conf import settings

#disable unwanted initialization and error management of kivy
os.environ['KIVY_DOC_INCLUDE'] = "1"

import time
from rmap import rabbitshovel
from django.core.exceptions import ObjectDoesNotExist
from rmap.utils import nint
from rmap import jsonrpc

from rmap import __version__
import rmap.settings
import argparse

import django

# go to share dir for virtualenv
ve=os.getenv("VIRTUAL_ENV")
if ve is not None:
    os.chdir(ve+"/share/rmap")

django.setup()

from rmap.stations.models import StationMetadata
from rmap.stations.models import Sensor, SensorType
import rmap.rmap_core

parser = argparse.ArgumentParser(description='Configure rmap boards. Thera are some option that are action options and others that are parameter options')
parser.add_argument('--version', action='version', version="%(prog)s "+__version__)

parser.add_argument('--list_stations',action="store_true", help="list all stations, board and transports")
parser.add_argument('--list_boards',action="store_true", help="list all board on station and transports")
parser.add_argument('--wizard',action="store_true", help="wizard configuration tool (simple set user, password, location on station")
parser.add_argument('--delsensor',action="store_true", help="del sensor from module of station")
parser.add_argument('--delsensors',action="store_true", help="ATTENTIONS delete ALL sensor from module of station")
parser.add_argument('--addsensor',action="store_true", help="add sensor to module of station")
parser.add_argument('--addsensors_by_template',  default=None, choices=rmap.rmap_core.template_choices, help="configure sensor for a module of station by template")
parser.add_argument('--config_station',action="store_true", help="configure board connected to station")
parser.add_argument('--dump_station',action="store_true", help="dump station configuration in json format with natural keys")
parser.add_argument('--upload_to_server',action="store_true", help="upload configuration to server")


parser.add_argument('--station_slug',  default=rmap.settings.stationslug, help="work on station defined by this slug")
parser.add_argument('--board_slug',  default=None, help="work on board defined by this slug")
parser.add_argument('--device',  default=None, help="use this device for serial transport")
parser.add_argument('--baudrate',  default=None, help="use this baudrate for serial transport")
parser.add_argument('--transport',  default="serial",choices=["serial","tcpip","amqp"],help="work on this transport")
parser.add_argument('--host',  default="master",choices=['master', 'master2', 'master3', 'master4'],help="work on this named board only")
parser.add_argument('--lon',  default=None, help="longitude of station")
parser.add_argument('--lat',  default=None, help="latitude of station")
parser.add_argument('--height',  default=None, help="height of station in meters")
parser.add_argument('--stationname',  default=None, help="name of station")
parser.add_argument('--username',  default=None, help="username for authentication")
parser.add_argument('--password',  default=None, help="password for authentication")
parser.add_argument('--server',  default="rmap.cc", help="rmap server")
parser.add_argument('--queue',  default="rmap", help="queue for amqp broker")
parser.add_argument('--exchange',  default="rmap", help="exchange for amqp broker")
parser.add_argument('--bluetoothname',  default="HC-05", help="name of the bluetooth device")
#parser.add_argument('--sensortemplate',  default=None, help="sensor template definition")
parser.add_argument('--sensorname',  default=None, help="sensor name")
drivers=[]
for driver in Sensor.SENSOR_DRIVER_CHOICES:
    drivers.append(driver[0])
parser.add_argument('--driver',  default="TMP", help="sensor driver",choices=drivers)
types=[]
for type in SensorType.objects.all():
    types.append(type.type)
parser.add_argument('--type',  default="TMP", help="sensor type",choices=types)
parser.add_argument('--i2cbus',  default=1, help="i2c smbus number")
parser.add_argument('--address',  default=72, help="i2c sensor address")
parser.add_argument('--node',  default=1, help="RF24Network node")
parser.add_argument('--timerange',  default="254,0,0", help="sensor timerange (see tables)")
parser.add_argument('--level',  default="103,2000", help="sensor level (see tables)")

parser.add_argument('--addboard',action="store_true", help="add board to module of station")
parser.add_argument('--serialactivate',action="store_true", help="activate serial transport")
parser.add_argument('--mqttactivate',action="store_true", help="activate mqtt transport")
parser.add_argument('--mqttusername',  default="", help="mqtt username")
parser.add_argument('--mqttpassword',  default="", help="mqtt password")
parser.add_argument('--mqttsamplerate',type=int,  default=5, help="mqtt samplerate for sensorsin seconds")
parser.add_argument('--mqttrootpath',  default="rmap", help="mqtt topic root path")
parser.add_argument('--mqttmaintpath',  default="rmap", help="mqtt topic maint path for admin RPC")
parser.add_argument('--network',  default="fixed", help="network (station type)",choices=("fixed","mobile"))

parser.add_argument('--bluetoothactivate', action="store_true", help="activate bluetooth transport")
parser.add_argument('--amqpactivate', action="store_true", help="activate amqp transport")
parser.add_argument('--amqpuser',  default="rmap", help="amqp user")
parser.add_argument('--amqppassword',  default="", help="amqp password")

parser.add_argument('--tcpipactivate', action="store_true", help="activate tcp/ip transport")
parser.add_argument('--tcpipname',  default="master", help="tcp/ip name")
parser.add_argument('--tcpipntpserver',  default="ntpserver", help="tcp/ip ntp server")

args = parser.parse_args()


if args.wizard:

    if (args.username is None or
        args.password is None or
        args.lon is None or
        args.lat is None):
        print " selected wizard without username or password or lat or lon or board"
        raise SystemExit(1)


    constantdata={}
    if not args.stationname is None:
        constantdata["B01019"]=args.stationname
    if not args.height is None:
        constantdata["B07030"]=str(int(float(args.height)*10))

    rmap.rmap_core.configdb(username=args.username,password=args.password,
                            station=args.station_slug,lat=args.lat,lon=args.lon,constantdata=constantdata,
                            network=args.network,
                            mqttusername=args.username,
                            mqttpassword=args.password,
                            mqttserver=args.server,
                            mqttsamplerate=args.mqttsamplerate,
                            mqttrootpath=args.mqttrootpath,
                            mqttmaintpath=args.mqttmaintpath,
                            bluetoothname=args.bluetoothname,
                            amqpusername=args.username,
                            amqppassword=args.password,
                            amqpserver=args.server,
                            queue=args.queue,
                            exchange=args.exchange,
                            board=args.board_slug,
                            activate=True,
                            stationname=args.stationname)

    print "END of wizard configuration"


if args.addboard:

    if (args.station_slug is None or
        args.board_slug is None or
        args.username is None):
        print " selected addboard without station_slug or board_slug or username"
        raise SystemExit(1)

    rmap.rmap_core.addboard(station_slug=args.station_slug,username=args.username,board_slug=args.board_slug,activate=True
                            ,serialactivate=args.serialactivate
                            ,mqttactivate=args.mqttactivate, mqttserver="rmap.cc"
                            ,mqttusername=args.mqttusername, mqttpassword=args.mqttpassword, mqttsamplerate=args.mqttsamplerate
                            ,bluetoothactivate=args.bluetoothactivate, bluetoothname=args.bluetoothname
                            ,amqpactivate=args.amqpactivate, amqpusername=args.amqpuser, amqppassword=args.amqppassword
                            ,amqpserver="rmap.cc", queue="rmap", exchange="rmap"
                            ,tcpipactivate=args.tcpipactivate, tcpipname=args.tcpipname, tcpipntpserver=args.tcpipntpserver)


if args.delsensor:

    if (   args.sensorname is None
        or args.station_slug is None
        or args.username is None
        or args.board_slug is None):

        print " selected delsensor without  station_slug or username or board_slug or sensorname"
        raise SystemExit(1)

    rmap.rmap_core.delsensor(station_slug=args.station_slug,username=args.username,board_slug=args.board_slug,name=args.sensorname)

    print "END of delsensor configuration"


if args.delsensors:

    if (args.board_slug is None
        or args.station_slug is None
        or args.username is None):

        print " selected delsensor without station_slug or username or board_slug"
        raise SystemExit(1)

    rmap.rmap_core.delsensors(station_slug=args.station_slug,username=args.username,board_slug=args.board_slug)

    print "END of delsensors configuration"



if args.addsensor:

    if (   args.sensorname is None
        or args.station_slug is None
        or args.username is None
        or args.board_slug is None):

        print " selected addsensor without sensorname or station_slug or username orboard_slug"
        raise SystemExit(1)


    rmap.rmap_core.addsensor(station_slug=args.station_slug,username=args.username,board_slug=args.board_slug,name=args.sensorname,driver=args.driver,
                             type=args.type,i2cbus=args.i2cbus,address=args.address,node=args.node,
                             timerange=args.timerange,level=args.level)
    #,sensortemplate=args.sensortemplate)

    print "END of addsensor configuration"


if args.addsensors_by_template is not None:

    if (args.board_slug is None
        or args.station_slug is None
        or args.username is None):

        print " selected addsensors_by_template without station_slug or username or board_slug"
        raise SystemExit(1)


    rmap.rmap_core.addsensors_by_template(args.station_slug,args.username,args.board_slug,args.addsensors_by_template)

    print "END of addsensors_by_template configuration"


if args.list_stations:

    for mystation in StationMetadata.objects.all():
        print "STATION:", mystation
        print "slug=",mystation.slug

    print "END of station list"
    #raise SystemExit(0)

if args.list_boards:


    if (args.username is None or
        args.station_slug is None):
        print " selected list_boards without username or station_slug"
        raise SystemExit(1)


    mystation=StationMetadata.objects.get(slug=args.station_slug,ident__username=args.username)

    print "STATION:", mystation

    for board in mystation.board_set.all():
        print ">board: ", board.name," slug="+board.slug," active=",board.active
        try:
            if ( board.transportserial.active):
                print "\tSerial Transport device=",board.transportserial.device," baudrate=",board.transportserial.baudrate
                
        except ObjectDoesNotExist:
            print "\ttransport serial not present for this board"


        try:
            if ( board.transporttcpip.active):
                print "\tTCP/IP Transport", " hostname=",board.transporttcpip.name

        except ObjectDoesNotExist:

            print "\ttransport TCPIP not present for this board"

        try:
            if ( board.transportamqp.active):
                print "\tAMQP Transport", " amqpserver=",board.transportamqp.amqpserver,
                " exchange=",board.transportamqp.exchange, "queue=",board.transportamqp.queue

        except ObjectDoesNotExist:

            print "\ttransport AMQP not present for this board"


    print "END of board list"
    #raise SystemExit(0)


if args.config_station:

    if (args.username is None or
        args.station_slug is None):
        print " selected config_station without username or station_slug"
        raise SystemExit(1)

    rmap.rmap_core.configstation(transport_name=args.transport,station_slug=args.station_slug,
                                 board_slug=args.board_slug,
                                 device=args.device,baudrate=args.baudrate,host=args.host,username=args.username)

    print "END of station configuration"


if args.dump_station:

    if (args.username is None or
        args.station_slug is None):
        print " selected dump station without username or station_slug"
        raise SystemExit(1)

    print rmap.rmap_core.dumpstation(station=args.station_slug,user=args.username)


if args.upload_to_server:

    if (args.username is None or
        args.password is None or
        args.station_slug is None):
        print " selected upload_to_server without username or password or station_slug"
        raise SystemExit(1)

    rmap.rmap_core.sendjson2amqp(station=args.station_slug,user=args.username,password=args.password)

    print "END of upload_to_server configuration"
