import json
import sys
import time
import datetime
import Adafruit_DHT
import gspread
import picamera
import ast
import urllib
# import MySQLdb
import boto3
import botocore

from rpi_lcd import LCD
from oauth2client.service_account import ServiceAccountCredentials
from gpiozero import MotionSensor
from twilio.rest import Client
from decimal import *
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient

def login_open_sheet(oauth_key_file, spreadsheet):
    try:
        scope = ['https://spreadsheets.google.com/feeds']
        credentials = ServiceAccountCredentials.from_json_keyfile_name(oauth_key_file, scope)
        gc = gspread.authorize(credentials)
        worksheet = gc.open(spreadsheet).sheet1
        print("Successfully connected to Google Spreadsheet!")
        return worksheet
    except Exception as ex:
        print('Unable to login and get spreadsheet.')
        print('Google sheet login failed with error:', ex)
        sys.exit(1)

def smsAndEmailAlert():
    tablestaff = dynamodb.Table('staffdata')
    response = tablestaff.scan(
        ProjectionExpression='mobileno'
        )

    items = response['Items']
    for item in items:
        row = ast.literal_eval(str(item))
        rownum = row[u'mobileno']
        if temperature > 28 or temperature < 10:
            sms = "Alert! Temperature of server room as of {} is {} C".format(timestringth, temperature)
            print('.')
            message = client.api.account.messages.create(to=rownum,
                                                        from_=twilio_hp,
                                                        body=sms)
            my_rpi.publish("TempHumid", str(sms), 1)
            print("Sent sms and email: " + sms)

        if humidity > 60 or humidity < 40:
            sms = "Alert! Humidity of server room as of {} is {} %".format(timestringth, humidity)
            print('.')
            message = client.api.account.messages.create(to=rownum,
                                                        from_=twilio_hp,
                                                        body=sms)
            my_rpi.publish("TempHumid", str(sms), 1)
            print("Sent sms and email: " + sms)

        if pir.motion_detected:
            sms = "Alert! Motion detected in the server room at {}".format(timestring)
            print('.')
            message = client.api.account.messages.create(to=rownum,
                                                        from_=twilio_hp,
                                                        body=sms)
            my_rpi.publish("TempHumid", str(sms), 1)
            print("Sent sms and email: " + sms)

def uploadS3(filename, filepath):
    # Set the filename and bucket name
    bucket_name = 'seroma-bucket' # replace with your own unique bucket name
    exists = True

    try:
        s3.meta.client.head_bucket(Bucket=bucket_name)
    except botocore.exceptions.ClientError as e:
        error_code = int(e.response['Error']['Code'])
        if error_code == 404:
            exists = False

    if exists == False:
        s3.create_bucket(Bucket=bucket_name,CreateBucketConfiguration={'LocationConstraint': 'us-west-2'})

    s3.Object(bucket_name, filename).put(Body=open(filepath, 'rb'))
    print("File uploaded (" + filename + ")")

def customCallback(client, userdata, message):
    Emailmsg = "Email has been sent from topic " + message.topic + " with the message " + message.payload
	# print("Received a new message: ")
	# print(message.payload)
	# print("from topic: ")
	# print(message.topic)
	# print("-----------------------------------------\n\n")


# AWS IoT
host = "a2kupibgh98nl3.iot.us-west-2.amazonaws.com"
rootCAPath = "AWSIoTCerts/VeriSign-Class 3-Public-Primary-Certification-Authority-G5.pem"
certificatePath = "AWSIoTCerts/fe507b04c2-certificate.pem.crt.txt"
privateKeyPath = "AWSIoTCerts/fe507b04c2-private.pem.key"

my_rpi = AWSIoTMQTTClient("TempHumidPubSub")
my_rpi.configureEndpoint(host, 8883)
my_rpi.configureCredentials(rootCAPath, privateKeyPath, certificatePath)

my_rpi.configureOfflinePublishQueueing(-1)  # Infinite offline Publish queueing
my_rpi.configureDrainingFrequency(2)  # Draining: 2 Hz
my_rpi.configureConnectDisconnectTimeout(10)  # 10 sec
my_rpi.configureMQTTOperationTimeout(5)  # 5 sec

# Connect and subscribe to AWS IoT
my_rpi.connect()
my_rpi.subscribe("TempHumid", 1, customCallback)
time.sleep(2)

# Twilio
account_sid = "ACd9b0b07a900349ec39b8830fe6d60514"
auth_token = "50099ccd679d8e78c37c93b51fb764db"
client = Client(account_sid, auth_token)
twilio_hp = "+18043150706"

# PiCam
pir = MotionSensor(26, sample_rate=5,queue_len=1)
camera = picamera.PiCamera()

# Create an S3 resource
s3 = boto3.resource('s3',
         aws_access_key_id='AKIAJ2GBRVCPX7JOVTRQ',
         aws_secret_access_key='ZCpYeniO2fKkaDFgQ2DgVjoQVodCL+CRqGimmXfC')

# DynamoDB
dynamodb = boto3.resource('dynamodb',
         aws_access_key_id='AKIAJ2GBRVCPX7JOVTRQ',
         aws_secret_access_key='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',
         region_name='us-west-2')
table = dynamodb.Table('roomstatus')

# Misc
DHT_GPIO = 4
lcd = LCD()

# Google Docs
GDOCS_OAUTH_JSON = 'IoTCA1-StatusLogs-a5895fb81ef5.json'
GDOCS_SPREADSHEET_NAME = 'Server Room Status Logs'


# # MySQLdb
# host = "localhost"
# username = "IoTCA1"
# password = "robots1234"
# dbname = "IoTCA1"

# def connect_db(host,username,password,dbname):
#     try:
#         db = MySQLdb.connect(host,username,password,dbname)
#         print("Successfully connected to MySQL database!")
#         return db
#     except:
#         print("Error connecting to mySQL database")


print('Logging sensor measurements every minute.')
print('Press Ctrl-C to quit.')
worksheet = None
# db = None



while True:

    # if db is None:
    #     db = connect_db(host,username,password,dbname)
    #     curs = db.cursor()
    if worksheet is None:
        worksheet = login_open_sheet(GDOCS_OAUTH_JSON, GDOCS_SPREADSHEET_NAME)

    print('.')
    print('.')
    print('-------------- ROOM STATUS --------------')
    humidity, temperature = Adafruit_DHT.read_retry(11, DHT_GPIO)
    print(humidity, temperature)
    if humidity == None or temperature == None:
        temperature = 'None'
        humidity = 'None'
        print('Temperature: {}'.format(temperature))
        lcd.text('Temp: {}'.format(temperature), 1)
        print('Humidity: {}'.format(humidity))
        lcd.text('Humid: {}'.format(humidity), 2)
    else:
        temperature = Decimal(temperature)
        humidity = Decimal(humidity)
        print('Temperature: {:.1f} C'.format(temperature))
        lcd.text('Temp: {:.1f} C'.format(temperature), 1)
        print('Humidity: {:.1f} %'.format(humidity))
        lcd.text('Humid: {:.1f} %'.format(humidity), 2)

    try:
        worksheet.append_row((datetime.datetime.now(), temperature, humidity))
    except:
        print('Append error, logging in again')
        worksheet = None
        time.sleep(60 - int(time.strftime("%S", time.localtime())))
        continue
    timestringth = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    print('Wrote a row to Google Docs - {0}'.format(GDOCS_SPREADSHEET_NAME) + ' at ' + timestringth)
    print('-----------------------------------------')
    print('.')
    print('.')


    if int(time.strftime("%H", time.localtime())) > 19 or int(time.strftime("%H", time.localtime())) < 7:
        print('--------------- SECURITY ----------------')
        print('Detecting motion for the next minute...')
        pir.wait_for_motion(60 - int(time.strftime("%S", time.localtime())))
        if pir.motion_detected:
            # try:
            timestring = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            print ("Motion detected, taking picture and video at " + timestring)
            imgpath = '/home/pi/Desktop/CA2/static/PiCam/pictures/'+timestring+'.jpg'
            camera.capture(imgpath)
            camera.resolution = (640, 480)
            uploadS3(timestring+'.jpg', imgpath)
            vidpath = '/home/pi/Desktop/CA2/static/PiCam/videos/'+timestring+'.h264'
            camera.start_recording(vidpath)
            camera.wait_recording(10)
            camera.stop_recording()
            uploadS3(timestring+'.h264', vidpath)
            if humidity == 'None' or temperature == 'None':
                temperaturedb = 0
                humiditydb = 0
                table.put_item(
                    Item={
                        'datetimevalue': timestring,
                        'temp': temperaturedb,
                        'humidity': humiditydb,
                        'motion': pir.motion_detected,
                        'image': urllib.quote_plus(timestring)+".jpg",
                        'video': urllib.quote_plus(timestring)+".h264"
                    }
                )
            else:
                table.put_item(
                    Item={
                        'datetimevalue': timestring,
                        'temp': temperature,
                        'humidity': humidity,
                        'motion': pir.motion_detected,
                        'image': urllib.quote_plus(timestring)+".jpg",
                        'video': urllib.quote_plus(timestring)+".h264"
                    }
                )
            print("Inserted data into DynamoDB")
            # sql = ("INSERT into roomstatus (temp, humidity, motion, image, video) VALUES ('%s', '%s', '%s', '%s', '%s')" % (temperature, humidity, pir.motion_detected, 'PiCam/pictures/'+timestring+'.jpg', 'PiCam/videos/'+timestring+'.h264'))
            # curs.execute(sql)
            # db.commit()
            print('-----------------------------------------')
            print('.')
            timestring = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            print('Wrote a row to roomstatus at ' + timestring)
            print('.')
            smsAndEmailAlert()
            time.sleep((59 - int(time.strftime("%S", time.localtime()))))
            # except MySQLdb.Error as e:
            #     print e
            # except KeyboardInterrupt:
            #     update = False
            #     curs.close()
            #     db.close()
        else:
            print("No motion detected")
            timestring = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            if humidity == 'None' or temperature == 'None':
                temperaturedb = 0
                humiditydb = 0
                table.put_item(
                    Item={
                        'datetimevalue': timestring,
                        'temp': temperaturedb,
                        'humidity': humiditydb,
                        'motion': pir.motion_detected
                    }
                )
            else:
                table.put_item(
                    Item={
                        'datetimevalue': timestring,
                        'temp': temperature,
                        'humidity': humidity,
                        'motion': pir.motion_detected
                    }
                )
            print("Inserted data into DynamoDB")
            # sql = ("INSERT into roomstatus (temp, humidity, motion) VALUES ('%s', '%s', '%s')" % (temperature, humidity, pir.motion_detected))
            # curs.execute(sql)
            # db.commit()
            print('-----------------------------------------')
            print('.')
            print('Wrote a row to roomstatus at ' + timestring)
            print('.')
            smsAndEmailAlert()
    else:
        print("Still during office hours. Waiting until next minute to take readings.")
        print('.')
        print('.')
        timestring = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        if humidity == 'None' or temperature == 'None':
            temperaturedb = 0
            humiditydb = 0
            table.put_item(
                Item={
                    'datetimevalue': timestring,
                    'temp': temperaturedb,
                    'humidity': humiditydb,
                    'motion': pir.motion_detected
                }
            )
        else:
            table.put_item(
                Item={
                    'datetimevalue': timestring,
                    'temp': temperature,
                    'humidity': humidity,
                    'motion': pir.motion_detected
                }
            )
        print("Inserted data into DynamoDB")
        print('.')
        smsAndEmailAlert()
        time.sleep((59 - int(time.strftime("%S", time.localtime()))))


    print('-----------------------------------------')

    print('.')
