# File Name: app.py
# Modified Date: March 24, 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 and
#              it reads a file of itemlist.text and prints out to the console.

__author__ = "Inyoung Choung"

import tkinter
from tkinter import messagebox
from flask_sqlalchemy import SQLAlchemy
from flask import Flask, render_template, request


# 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(64))
    timestampe = 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()

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

def convert(weightT1, weightT2, weight2):
    if weightT1 == "lb":
        if weightT2 == "kg":
            weight2 = float(weight2) * 2.20462
        elif weightT2 == "g":
            weight2 = float(weight2) * 0.002205
    elif weightT1 == "kg":
        if weightT2 == "lb":
            weight2 = float(weight2) * 0.453592
        elif weightT2 == "g":
            weight2 = float(weight2) * 0.001
    elif weightT1 == "g":
        if weightT2 == "kg":
            weight2 = float(weight2) * 1000
        elif weightT2 == "lb":
            weight2 = float(weight2) * 453.592

    return weight2


def alert_message(message_arg):
    if message_arg is None:
        message = str("Please fill out all the forms.")
    else:
        message = message_arg
    return message


global newWeightForSecondItem

# end point where python gets user data from javascript
@app.route('/calculate', methods = ['GET'])
def calculate():

    # get value from html
    itemtype = (request.args.get('param1'))
    brandN1 = (request.args.get('param2'))
    brandN2 = (request.args.get('param3'))
    price1 = (request.args.get('param4'))
    price2 = (request.args.get('param5'))
    weight1 = (request.args.get('param6'))
    weightT1 = (request.args.get('param7'))
    weight2 = (request.args.get('param8'))
    weightT2 = (request.args.get('param9'))
    discount1 = (request.args.get('param10'))
    discountT1 = (request.args.get('param11'))
    discount2 = (request.args.get('param12'))
    discountT2 = (request.args.get('param13'))

    if (itemtype is None or itemtype == "" or
        brandN1 is None or brandN1 == "" or
        brandN2 is None or brandN2 == "" or
        price1 is None or price1 == "" or
        price2 is None or price2 == "" or
        weight1 is None or weight1 == "" or
        weightT1 is None or weightT1 == "" or
        weight2 is None or weight2 == "" or
        weightT2 is None or weightT2 == "" or
        discount1 is None or discount1 == "" or
        discountT1 is None or discountT1 == "" or
        discount2 is None or discount2 == "" or
        discountT2 is None or discountT2 == ""):
            # hide main window
            root = tkinter.Tk()
            root.withdraw()
            messagebox.showerror( "Alert - Empty fields", alert_message("Please fill out all the forms."))


    # after users values are accepted, do calculation.
    if weightT1 != weightT2:
        newWeightForSecondItem = convert(weightT1, weightT2, weight2)
        # both items have the same weight type from this point
    else:
        newWeightForSecondItem = weight2


    if discountT1 == "percentage":
        finalPrice1 = float((float(price1) - (float(price1) * (float(discount1) * float(0.01)))) / float(weight1))
    elif discountT1 == "dollar":
        finalPrice1 = float((float(price1) - float(discount1)) / float(weight1))


    if discountT2 == "percentage":
        finalPrice2 = float((float(price2) - (float(price2) * (float(discount2) * float(0.01)))) / float(newWeightForSecondItem))
    elif discountT2 == "dollar":
        finalPrice2 = float((float(price2) - (float(discount2))) / float(newWeightForSecondItem))



    if finalPrice1 > finalPrice2:
        priceDiff = round(float(finalPrice1 - finalPrice2), 3)
        print(brandN1 + str(" is cheaper by "), priceDiff)
        result = str(brandN1 + str(" is cheaper by ") + str(priceDiff) + str(" cents per unit weight "))
    elif finalPrice1 < finalPrice2:
        priceDiff = round(float(finalPrice2 - finalPrice1), 3)
        print(brandN2 + str(" is cheaper by "), priceDiff)
        result = str(brandN2 + str(" is cheaper by ") + str(priceDiff) + str(" cents per unit weight "))
    else:
        result = str("The price is equal so get anything!")

    # hide main window
    root = tkinter.Tk()
    root.withdraw()
    messagebox.showinfo("Calculation Result", result)


    try:
        # 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 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()
        return result
    # catch the exception and print it
    except ValueError:
        print(ValueError)
        print("failed to create new row")
        return -1


# File I/O - prints a list of grocery items
def writefile(path, word):
    # open a file for writing and create it if it doesn't exist.
    if path is None:
        # set a specific path
        filepath = "C:\In-young Choung\Computer Programming\Self Programming Files\grocerycalc\itemlist.txt"
        # output a file if it doesn't exist
        f = open(filepath, "w+")
        # write some texts inside the opened file
        f.write("chicken, ")
        f.write("milk")
        readfile(filepath)
    else: # when the path is specified
        filepath= path
        # output a file if it doesn't exist
        f = open(filepath, "w+")
        # write text that is passed as a paramter in the method
        f.write(word)


# read file that is created and pass filepath as a parameter
def readfile(filepath):
    # open the file in the defined path and "r" read it
    f = open(filepath, "r")
    if f.mode == 'r':
        # use read function to read the entire file.
        contents = f.read()

        #print the file content in the console
        print(contents)


# main method
if __name__ == '__main__':
    app.debug = True
    # app.debug = False
    writefile(None, None)
    app.run()