# File Name: app.py
# Modified Date: April 15, 2017
# Description: This python file contains database configuration and creates database tables and fields using flask_sqlalchemy.
#              Users' values passed from Javascript are inserted into the database table.
#              It also has mapping request to interact with specific html files.
# Method Level Comment: Python Convention (inside function)
__author__ = "Inyoung Choung"

from flask_sqlalchemy import SQLAlchemy
from flask import Flask, render_template, request
from implementation import Impl
import datetime

# passing the whole app code to Flask
app = Flask(__name__)

# Configuration for Database ORM - database name: grocery app, user: groceryadmin, password: VKov2q3XTtqj6w9o
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://groceryadmin:VKov2q3XTtqj6w9o@localhost/groceryapp'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

# Database instantiation
db = SQLAlchemy(app)

# database ORM calc table - 3 columns
class Calc(db.Model):
    __tablename__="calc"

    # database fields
    id = db.Column(db.Integer, primary_key=True)
    result = db.Column(db.String(255))
    timestamp = db.Column(db.TIMESTAMP)

    # adding constraints to delete all data in Item when calc is deleted.
    item = db.relationship('Item', backref='calc', cascade='all, delete-orphan', lazy='dynamic')

# database ORM item table - 9 columns
class Item(db.Model):
    __tablename__ = "items"

    # database fields
    id = db.Column(db.Integer, primary_key=True)
    item_type = db.Column(db.String(64))
    brand_name = db.Column(db.String(64))
    price = db.Column(db.DECIMAL)
    weight = db.Column(db.DECIMAL)
    weight_type = db.Column(db.String(5))
    discount = db.Column(db.DECIMAL)
    discount_type = db.Column(db.String(20))
    calc_id = db.Column(db.Integer, db.ForeignKey(Calc.id))

# create all the tables defined as classes
# db.create_all()


@app.route('/', methods = ['GET', 'POST'])
def index():
    """
    mapping request to URLs
    :return: render_template('index.html')
    """
    if request.method == 'GET':
        # renders to html file
        return render_template('index.html')


# These variables are declared as global.
global newWeightForSecondItem
global list


@app.route('/calculate', methods=['GET'])
def calculate():
    """
    end point where python gets user data from javascript.
    :return: 'Successful'
    """
    # get value from javascript.
    itemtype = str((request.args.get('param1')))
    brandN1 = str((request.args.get('param2')))
    brandN2 = str((request.args.get('param3')))
    price1 = str((request.args.get('param4')))
    price2 = str((request.args.get('param5')))
    weight1 = str((request.args.get('param6')))
    weightT1 = str((request.args.get('param7')))
    weight2 = str((request.args.get('param8')))
    weightT2 = str((request.args.get('param9')))
    discount1 = str((request.args.get('param10')))
    discountT1 = str((request.args.get('param11')))
    discount2 = str((request.args.get('param12')))
    discountT2 = str((request.args.get('param13')))

    # instantiate an object of Impl and pass arguments.
    implObj = Impl(itemtype, brandN1, brandN2, price1, price2, weight1, weightT1, weight2,
            weightT2, discount1,discountT1, discount2, discountT2)

    try:
        # save data into calc table of the database.
        calc = Calc(result = implObj.get_result(), timestamp = '{:%Y-%b-%d %H:%M:%S}'.format(datetime.datetime.now()))
        # insert a new row into the database.
        db.session.add(calc)

        # define array variables to be ready to match with db columns.
        brand_names = [brandN1, brandN2]
        prices = [price1, price2]
        weights = [weight1, weight2]
        weight_types = [weightT1, weightT2]
        discounts = [discount1, discount2]
        discount_types = [discountT1, discountT2]

        # iteration variable for loop.
        i = 0
        # loop twice to save two compared items into item table of the database.
        for i in range(0, 2):
            item = Item(item_type=itemtype, brand_name=brand_names[i], price=prices[i],
                        weight=weights[i], weight_type=weight_types[i], discount=discounts[i],
                        discount_type=discount_types[i])

            # insert a new row into the database.
            db.session.add(item)

        # write it to db disk once the loop is done.
        db.session.commit()
        # initialize empty list to collect item objects.
        list = []
        # loop for the result of the query to display brand_name column rows of Item table.
        for row in db.session.query(Item, Item.brand_name).all():
            # add brand name into the list
            list.append(row.brand_name)

        # sorts the item list by the alphabetical order.
        implObj.sort(list)

        # calls writefile function and pass the sorted list.
        implObj.writefile(None, list)
        implObj.readfile()

        return 'Successful'
    # catch the exception and print it.
    except ValueError:
        print(ValueError)
        print("failed to create new row")
        return -1


if __name__ == '__main__':
    # main method that starts the application.

    # debugging purpose.
    app.debug = True
    app.run()


