#!/usr/bin/python3

import sqlite3
import json
import sys
import os

"""
Reads the API KEY, that must be passed as first command line argument.

:returns: Recovered API KEY.
:raises Exception: Th KEY couldn't be red.
"""
def readKey():
    try:
        #print(sys.argv[0])
        key = sys.argv[1]
        return key
    except Exception as e:
        print("Error parsing API KEY: " + str(e))
        raise

"""
Reads the JSON data, that must be passed as second command line argument.

:returns: Recovered data, in JSON format.
:raises Exception: The data couldn't be red or converted to JSON.
"""
def readData():
    try:
        print(sys.argv[2])
        data = json.loads(sys.argv[2])
        return data
    except Exception as e:
        print("Error parsing data: " + str(e))
        raise

"""
Verifies that the API key matches the player data and that it exists in th DB.

:param db: Connection to the database.
:returns: Connection to the database.
:param data: Data in json format.
:param key: API KEY.
:returns: True if key and player match, False otherwise.
:raises IntegrityError: The queryes couldn't bre executed.
"""
def verifyKey(db, data, key):
    print('Verifying KEY...')
    status = False
    try:
        uid = data["uid"]
        cursor = db.cursor()
        cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key))
        if cursor.fetchone()[0] == 1:
            status = True
        cursor.close()
    except sqlite3.IntegrityError as e:
        print("Error executing statement: " + str(e))
        raise
    return status

"""
Opens the database file and deletes from the user tables

:param name: The path to the sqlite database.
:returns: Connection to the database.
:raises IntegrityError: The queryes couldn't bre executed.
:raises IOError: The sqlite file couldn't be created.
"""
def openDatabase(name):
    print('Configuring database...')
    try:
        db = sqlite3.connect(name)
        return db
    except IOError as e:
        print("I/O Error connecting to database " + name + ": " + str(e))
        raise


"""
Inserts a row into the database.

:param db: Connection to the database.
:param table: Name of the table to insert into.
:param values: List of values to insert.
:raises IntegrityError: The insert query was unsuccesfull.
"""
def insert(db, table, values):
    cursor = db.cursor()
    placeholders = ''
    for x in range(0, len(values)):
        placeholders = placeholders + '?, '
    placeholders = placeholders[:len(placeholders) - 2]
    query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')'
    try:
        cursor.execute(query, values)
    except sqlite3.IntegrityError as e:
        print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e))
        raise
    cursor.close;

"""
Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft,
run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces,
run_drop_shapeshifting).

:param db: Sqlite database connection.
:param data: JSON data.
"""
def parseRun(db, data):
    print("Parsing run...")
    cursor = db.cursor()
    uid = data["uid"]
    dtime = data["dtime"]
    # Check if run has already been inserted.
    cursor.execute("SELECT count(id) AS c FROM run WHERE uid = ? AND dtime = ?;", (uid, dtime))
    if (cursor.fetchone()[0] > 0):
        print("    Run already in database. Stopping....")
        return;
    area = data["area"]
    stage = data["stage"]
    difficulty = data["difficulty"]
    win = data["win"]
    time = data["time"]
    mana = data["mana"]
    energy = data["energy"]
    crystal = data["crystal"]
    helper = data["helper"]
    cursor.execute("SELECT max(id) + 1 AS id FROM run;")
    id = cursor.fetchone()[0]
    if id == None:
        id = 1
    insert(db, "run", (uid, id, dtime, area, stage, difficulty, win, time, mana, energy, crystal, helper))
    if data["shapeshifting"] > 0:
        insert(db, "run_drop_shapeshifting", (id, data["shapeshifting"]))
    if data["sd"] > 0:
        insert(db, "run_drop_sd", (id, data["sd"]))
    if data["sd"] > 0:
        insert(db, "run_drop_unit", (id, data["unit"]))
    for rune in data["rune"]:
        rune_id = rune["id"]
        rune_type = rune["type"]
        slot = rune["slot"]
        stars = rune["stars"]
        ancient = rune["ancient"]
        quality = rune["quality"]
        value = rune["value"]
        efficiency = rune["efficiency"]
        main_stat = rune["main_stat"]
        main_stat_value = rune["main_stat_value"]
        innate_stat = rune["innate_stat"]
        innate_stat_value = rune["innate_stat_value"]
        substat_1 = rune["substat_1"]
        substat_1_value = rune["substat_1_value"]
        substat_2 = rune["substat_2"]
        substat_2_value = rune["substat_2_value"]
        substat_3 = rune["substat_3"]
        substat_3_value = rune["substat_3_value"]
        substat_4 = rune["substat_4"]
        substat_4_value = rune["substat_4_value"]
        insert(db, "run_drop_rune", (id, rune_id, rune_type, slot, stars, ancient, quality, value, efficiency, main_stat, main_stat_value, innate_stat, innate_stat_value, substat_1, substat_1_value, substat_2, substat_2_value, substat_3, substat_3_value, substat_4, substat_4_value))
    for item in data["item"]:
        item_id = item["id"]
        quantity = item["quantity"]
        insert(db, "run_drop_item", (id, item_id, quantity))
    for pieces in data["unit_pieces"]:
        pieces_id = pieces["id"]
        quantity = pieces["quantity"]
        insert(db, "run_drop_unit_pieces", (id, pieces_id, quantity))
    for party in data["party"]:
        unit_id = party["unit_id"]
        unit_master_id = party["unit_master_id"]
        insert(db, "run_party", (id, unit_master_id, unit_id))
    db.commit()

"""
Begin script
"""
data = readData()
key = readKey()
db = openDatabase(os.path.dirname(os.path.realpath(sys.argv[0])) + '/../sw.sqlite')
if verifyKey(db, data, key) == False:
    print("Invalid API KEY...")
    sys.exit(-1)
else:
    parseRun(db, data)
sys.exit(0)


