from customtkinter import *
from tkinter import messagebox
from systemclass import System
import json
import os


root = CTk()
root.after(0, lambda:root.resizable(0,0)) #disables resizing of the window
root.after(0, lambda:root.state('zoomed')) #sets window state to zoomed/maximized
root.title("Globe One App Lite")

        
#Frames
register_frame = CTkFrame(root, fg_color = "light blue", width = 500, height = 500)
log_in_frame = CTkFrame(root, fg_color = "light blue", width = 500, height = 500)

user_frame = CTkFrame(root, fg_color = "lightblue", width = 1500, height = 245)
menu_frame = CTkFrame(root, fg_color = "blue", width = 1500, height = 500)

buy_load_frame = CTkFrame(menu_frame, fg_color = "green", width = 780, height = 500)
buy_promo_frame = CTkFrame(menu_frame, fg_color = "light green", width = 780, height = 500)
promo1_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)
promo2_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)
promo3_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)
promo4_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)
promo5_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)
promo6_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)
promo7_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)
promo8_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)
promo9_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)
promo10_frame = CTkFrame(buy_promo_frame, fg_color="lightblue", width=370, height=500)

send_load_frame = CTkFrame(menu_frame, fg_color = "orange", width = 780, height = 500)
view_subs_frame= CTkFrame(menu_frame, fg_color = "green", width = 750, height = 500)
view_subs_frameSB= CTkScrollableFrame(view_subs_frame, fg_color="yellow", width = 750, height = 500)
transaction_frame = CTkFrame(menu_frame, fg_color = "green", width = 750, height = 500)
transaction_frameSB = CTkScrollableFrame(transaction_frame, fg_color = "red", width = 750, height = 500)

#Function/command for switching from register frame to login frame
def switch_to_login():
    log_in_frame.pack(expand = 1, fill = BOTH)
    register_frame.pack_forget()
    user_frame.pack_forget()
    input_num_text = CTkLabel(log_in_frame, text = "Mobile Number", text_color = "Black", font = ("Arial", 20)) 
    input_num_text.place(x = 460, y = 270)
    input_pin_text = CTkLabel(log_in_frame, text = "PIN", text_color = "Black", font = ("Arial", 20)) 
    input_pin_text.place(x = 460, y = 370)
    
#Function/command for switching from login frame to register frame
def switch_to_reg():
    register_frame.pack(expand = 1, fill = BOTH)
    user_frame.pack_forget()
    log_in_frame.pack_forget()
    

account_number = ""
def register():
    global account_number
    global system
    user_number = reg_num_entry.get().strip()
    user_pin = reg_pin_entry.get().strip()
    system = System(user_number, user_pin)
    
    #checks user input, if invalid, will show an error messagebox or window
    if user_number == "":
        messagebox.showerror("ERROR", "PLEASE INPUT YOUR NUMBER")
    elif len(user_number) != 11:
        messagebox.showerror("ERROR", "INVALID NUMBER")
    elif user_pin == "":
        messagebox.showerror("ERROR", "PLEASE INPUT YOUR PIN")
    elif len(user_pin) != 4:
        messagebox.showerror("ERROR", "INVALID PIN")
    else:
        #check if the account number file exists
        if os.path.exists(f"{user_number}.json"):
            messagebox.showerror("ERROR", "THIS ACCOUNT ALREADY EXISTS")
        else:
            system.register()
            account_number = user_number
            to_menu()

def login():
    global account_number
    global system
    user_number = login_num_entry.get().strip()
    user_pin = login_pin_entry.get().strip()
    system = System(user_number, user_pin)
    validation = system.login()

    #checks user input, if invalid, will show an error messagebox or window
    if user_number == "":
            messagebox.showerror("ERROR", "PLEASE INPUT YOUR NUMBER")
    elif len(user_number) != 11:
            messagebox.showerror("ERROR", "INVALID NUMBER")
    elif os.path.exists(f"{user_number}.json"):
        if user_pin == "":
            messagebox.showerror("ERROR", "PLEASE INPUT YOUR PIN")
        elif len(user_pin) != 4:
            messagebox.showerror("ERROR", "INVALID PIN")
        elif validation == -1:
            messagebox.showerror("ERROR", "THIS ACCOUNT NUMBER DOESN'T EXIST")
        elif validation == -2:
            messagebox.showerror("ERROR", "WRONG PIN")
        elif validation == -3:
            messagebox.showerror("ERROR", "THIS ACCOUNT NUMBER DOESN'T EXIST")
        elif validation == 1:
            account_number = user_number
            to_menu()
        else:
            messagebox.showerror("ERROR", "LOG IN ERROR, PLEASE TRY AGAIN")
    else:
        messagebox.showerror("ERROR", "THIS ACCOUNT NUMBER DOESN'T EXIST")


#shows the user frame(yung frame sa taas) that contains user details(account number and load balance)(pede pa dagdagan suggest lang kau)
def user_details():
    user_frame.pack(side = TOP)
    with open(f"{account_number}.json", mode = "r+") as f:
            acc_data = json.load(f)
    #Displays account number
    user_num_lb = CTkLabel(user_frame, text = "Account Number", text_color = "Black", font = ("Arial", 30))
    user_num_lb.place(x = 200, y = 100)
    user_num_text = CTkLabel(user_frame, text = account_number, text_color = "Black", font = ("Arial", 25))
    user_num_text.place(x = 200, y = 150)

    #Displays load balance
    acc_balance_text = CTkLabel(user_frame, text = "P" + str(acc_data["balance"]) + ".00", text_color = "black", font = ("Arial", 25))
    acc_balance_text.place(x = 700, y = 100)
    acc_balance_lb = CTkLabel(user_frame, text = "Load Balance", text_color = "black", font = ("Arial", 25))
    acc_balance_lb.place(x = 700, y = 140)

    #Log out button 
    log_out_btn =  CTkButton(user_frame, text = "Log out", text_color = "Black", font = ("Arial", 12), width = 25, fg_color = "yellow", border_width=5, command = log_out)
    log_out_btn.place(x = 1250, y = 10)


#shows the main menu(yung frame sa baba) 
def to_menu():
    user_details()
    menu_frame.pack(side = BOTTOM)
    log_in_frame.pack_forget()
    register_frame.pack_forget()

    #Main buttons
    buy_load_btn = CTkButton(menu_frame, text = "Buy Load", text_color = "Black", font = ("Arial", 20), width = 150, height = 35, fg_color = "light blue", command = to_buy_load)
    buy_load_btn.place(x = 100, y = 100)

    buy_promo_btn = CTkButton(menu_frame, text = "Buy Promo", text_color = "Black", font = ("Arial", 20), width = 150, height = 35, fg_color = "light blue", command = to_buy_promo)
    buy_promo_btn.place(x = 100, y = 200)

    send_load_btn = CTkButton(menu_frame, text = "Send Load", text_color = "Black", font = ("Arial", 20), width = 150, height = 35, fg_color = "light blue", command = to_send_load)
    send_load_btn.place(x = 100, y = 300)
 
    view_subs_btn = CTkButton(menu_frame, text = "View Subscriptions", text_color = "Black", font = ("Arial", 20), width = 150, height = 35, fg_color = "light blue", command = to_view_subs)
    view_subs_btn.place(x = 300, y = 150)

    transaction_btn = CTkButton(menu_frame, text = "Transaction History", text_color = "Black", font = ("Arial", 20), width = 150, height = 35, fg_color = "light blue", command = to_transaction_history)
    transaction_btn.place(x = 300, y = 250)


#Used to restrict user from typing inputs other than numbers/digits
#Also restricts the user from typing more characters after the required length of input is exceeded
def validate(P):
        if len(P) == 0:
            return True
        elif len(P) < 12 and P.isdigit():
            return True
        else:
            return False
def validate_pin(P):
        if len(P) == 0:
            return True
        elif len(P) < 5 and P.isdigit():
            return True
        else:
            return False
def validate_load_amount(P):
    if len(P) == 0:
        return True
    elif len(P) < 5 and P.isdigit():
        return True
    else:
        return False
vcmd = (root.register(validate), '%P')
vcmd_pin = (root.register(validate_pin), '%P')
vcmd_load = (root.register(validate_load_amount), '%P')


#shows the buy load frame
def to_buy_load():
    buy_load_frame.place(x = 600, y = 0)
    buy_load_frame.tkraise()

    load_amount_text = CTkLabel(buy_load_frame, text = "Enter load amount (P10 to P2,000)", text_color = "Black", font = ("Arial", 20))
    load_amount_text.place(x = 100, y = 150)
    load_amount_input = CTkEntry(buy_load_frame, validate = "key", validatecommand=vcmd_load, width = 300, font = ("Arial", 20), text_color="black", fg_color = "white", border_width=2, border_color="black")
    load_amount_input.place(x = 100, y = 200)

    #Takes the user input in the load amount entry
    def get_load():
        load_amount = load_amount_input.get().strip()
        if load_amount == "":
            messagebox.showerror("ERROR", "PLEASE INPUT LOAD AMOUNT")
        elif int(load_amount) > 2000:
            messagebox.showerror("ERROR", "MAXIMUM OF P2000 ONLY! PLEASE TRY AGAIN.")
        elif int(load_amount) < 10:
            messagebox.showerror("ERROR", "MINIMUM OF P10 ONLY! PLEASE TRY AGAIN.")
        else:
            system.buyload(load_amount)
            user_details() #displays the updated user frame

    buyload_btn = CTkButton(buy_load_frame, text = "BUY", text_color = "white", font = ("Arial", 20, "bold"), width = 300, height = 35, fg_color = "blue", command = get_load)
    buyload_btn.place(x = 100, y = 300)
    

#displays the selected promo's details(promo name, price, duration)
def show_promo_details(promo_frame, promo_price, description, selected_promo):
    promo_frame.place(x=400, y=0)
    promo_frame.tkraise()
    promo_name_lb = CTkLabel(promo_frame, text=selected_promo, font = ("Arial", 20), text_color="black")
    promo_name_lb.place(x = 50, y = 50)
    promo_price_lb = CTkLabel(promo_frame, text = f'P{promo_price}', font = ("Arial", 20), text_color="black")
    promo_price_lb.place(x = 200, y = 50)

    description_lb = CTkLabel(promo_frame, text = description, text_color="Black", font=("Arial", 20))
    description_lb.place(x = 100, y = 200)
    
    subscribe_btn = CTkButton(promo_frame, text = "Subscribe", fg_color="blue", text_color="white", font=("Arial", 15, "bold"), command=lambda: [system.buypromo(selected_promo, promo_price), user_details()])
    subscribe_btn.place(x = 100, y = 300)


#show buy promo
def to_buy_promo():
    buy_promo_frame.place(x = 600, y = 0)
    buy_promo_frame.tkraise()

    promo_list = {0:["Go50",50, 3], 1:["UnliCalls", 20, 1], 2:["Go99", 99, 7], 3:["Unlidata", 50, 1], 4:["SuperXclusive199", 199, 15], 5:["UnliGo299", 299, 15], 6:["Go199", 199, 7], 7:["ML10", 10, 3], 8:["GoUNLI350", 350, 30], 9:["Go129", 129, 7]}
    
    CTkLabel(buy_promo_frame, text = "Available Promos", font = ("Arial", 25), text_color="Black").place(x=100, y=20)

    promo1_des = "PROMO DESCRIPTION" #temporary lang to, lalagyan ng promo description lahat ng promo
    promo1 = CTkButton(buy_promo_frame, text = promo_list[0][0], text_color = "Black", font = ("Arial", 20), width = 130, height = 35, command=lambda: show_promo_details(promo1_frame, promo_list[0][1], promo1_des, promo_list[0][0]))
    promo2 = CTkButton(buy_promo_frame, text = promo_list[1][0], text_color = "Black", font = ("Arial", 20), width = 130, height = 35, command=lambda: show_promo_details(promo2_frame, promo_list[1][1], promo1_des, promo_list[1][0]))
    promo3 = CTkButton(buy_promo_frame, text = promo_list[2][0], text_color = "Black", font = ("Arial", 20), width = 130, height = 35, command=lambda: show_promo_details(promo3_frame, promo_list[2][1], promo1_des, promo_list[2][0]))
    promo4 = CTkButton(buy_promo_frame, text = promo_list[3][0], text_color = "Black", font = ("Arial", 20), width = 130, height = 35, command=lambda: show_promo_details(promo4_frame, promo_list[3][1], promo1_des, promo_list[3][0]))
    promo5 = CTkButton(buy_promo_frame, text = promo_list[4][0], text_color = "Black", font = ("Arial", 17), width = 80, height = 35, command=lambda: show_promo_details(promo5_frame, promo_list[4][1], promo1_des, promo_list[4][0]))
    promo6 = CTkButton(buy_promo_frame, text = promo_list[5][0], text_color = "Black", font = ("Arial", 20), width = 130, height = 35, command=lambda: show_promo_details(promo6_frame, promo_list[5][1], promo1_des, promo_list[5][0]))
    promo7 = CTkButton(buy_promo_frame, text = promo_list[6][0], text_color = "Black", font = ("Arial", 20), width = 130, height = 35, command=lambda: show_promo_details(promo7_frame, promo_list[6][1], promo1_des, promo_list[6][0]))
    promo8 = CTkButton(buy_promo_frame, text = promo_list[7][0], text_color = "Black", font = ("Arial", 20), width = 130, height = 35, command=lambda: show_promo_details(promo8_frame, promo_list[7][1], promo1_des, promo_list[7][0]))
    promo9 = CTkButton(buy_promo_frame, text = promo_list[8][0], text_color = "Black", font = ("Arial", 20), width = 130, height = 35, command=lambda: show_promo_details(promo9_frame, promo_list[8][1], promo1_des, promo_list[8][0]))
    promo10 = CTkButton(buy_promo_frame, text = promo_list[9][0], text_color = "Black", font = ("Arial", 20), width = 130, height = 35, command=lambda: show_promo_details(promo10_frame, promo_list[9][1], promo1_des, promo_list[9][0]))

    promo1.place(x = 50, y = 100)
    promo2.place(x = 50, y = 180)
    promo3.place(x = 50, y = 260)
    promo4.place(x = 50, y = 340)
    promo5.place(x = 50, y = 420)
    promo6.place(x = 200, y = 100)
    promo7.place(x = 200, y = 180)
    promo8.place(x = 200, y = 260)
    promo9.place(x = 200, y = 340)
    promo10.place(x = 200, y = 420)
    

#show send load frame (dipa tapos)
def to_send_load():
    send_load_frame.place(x = 600, y = 0)
    send_load_frame.tkraise()


    receiver_num_text = CTkLabel(send_load_frame, text = "Recipient's Number", text_color = "Black", font = ("Arial", 20))
    receiver_num_text.place(x = 150, y = 100)
    receiver_num = CTkEntry(send_load_frame, validate="key",validatecommand=vcmd, width = 300, font = ("Arial", 20), text_color="black", fg_color = "white", border_color="black", border_width=2 )
    receiver_num.place(x = 400, y = 100)

    load_amount_text = CTkLabel(send_load_frame, text = "Amount:", text_color = "Black", font = ("Arial", 20))
    load_amount_text.place(x = 150, y = 200)
    load_amount_ent = CTkEntry(send_load_frame, validate = "key", validatecommand=vcmd_load, width = 300, font = ("Arial", 20), text_color="black", fg_color = "white", border_color="black", border_width=2 )
    load_amount_ent.place(x = 300, y = 200)

    #takes user input from the load amount and recipient entry
    def get_input():
        load_amount = load_amount_ent.get().strip()
        recipient = receiver_num.get().strip()
        
        if recipient == "":
            messagebox.showerror("ERROR", "PLEASE INPUT RECIPIENT NUMBER")
        elif len(recipient) != 11:
                messagebox.showerror("ERROR", "INVALID NUMBER")
        elif os.path.exists(f"{recipient}.json"):         
            if recipient == account_number:
                messagebox.showerror("ERROR", "YOU CANNOT SEND LOAD TO YOUR OWN NUMBER")
            elif load_amount == "":
                messagebox.showerror("ERROR", "PLEASE INPUT LOAD AMOUNT")
            else:    
                system.sendload(recipient, load_amount)
                user_details() #displays the updated user frame
        else:
             messagebox.showerror("ERROR", "THIS ACCOUNT DOESN'T EXIST")

    buyload_btn = CTkButton(send_load_frame, text = "SEND", text_color = "Black", font = ("Arial", 12), width = 15, fg_color = "white", border_width=10, command = get_input)
    buyload_btn.place(x = 300, y = 400)


#show active promos frame
def to_view_subs():
    view_subs_frame.place(x = 600, y = 0)
    view_subs_frame.tkraise()
    view_subs_frameSB.pack()

    #destroy pre-existing labels to avoid repeated display of labels
    for widgets in view_subs_frameSB.winfo_children():
        widgets.destroy()

    #displays all the active promos in the account
    with open(f"{account_number}.json", mode = "r+") as f:
        acc_data = json.load(f)
        active_promos = acc_data["promos"]
        CTkLabel(view_subs_frameSB, text = "Active Promos", text_color = "black", font = ("Arial", 20, "bold"), width = 20).pack(pady = 10)
        for p in active_promos:
            act_promos_txt = CTkLabel(view_subs_frameSB, text = p, text_color = "black", font = ("Arial", 20), width = 20)
            act_promos_txt.pack()


#show transaction history
def to_transaction_history():
    transaction_frame.place(x = 600, y = 0)
    transaction_frame.tkraise()
    transaction_frameSB.pack()

    #destroy pre-existing labels to avoid repeated display of labels
    for widgets in transaction_frameSB.winfo_children():
        widgets.destroy()

    #displays all transactions
    with open(f"{account_number}.json", mode = "r+") as f:
        acc_data = json.load(f)
        transactions = acc_data["transac_history"]
        CTkLabel(transaction_frameSB, text = "Transaction History", text_color="black", font = ("Arial", 20, "bold"), width = 20).pack(pady = 10)
        for t in transactions:
            transac_history_txt = CTkLabel(transaction_frameSB, text = t, text_color = "black", font = ("Arial", 20), width = 20)
            transac_history_txt.pack()


#log out 
def log_out():
    user_frame.pack_forget()
    menu_frame.pack_forget()
    for widgets in user_frame.winfo_children():
         widgets.destroy()
    switch_to_login()


#Register Account Number
input_num_text = CTkLabel(register_frame, text = "Mobile Number", text_color = "Black", font = ("Arial", 20)) 
input_num_text.place(x = 460, y = 270)
input_pin_text = CTkLabel(register_frame, text = "PIN", text_color = "Black", font = ("Arial", 20)) 
input_pin_text.place(x = 460, y = 370)

reg_num_entry = CTkEntry(register_frame, validate="key",validatecommand=vcmd, text_color="black", width = 370, height = 35, border_width=1, fg_color = "white", font = ("Arial", 20))
reg_num_entry.place(x = 460, y = 300)
reg_pin_entry = CTkEntry(register_frame, validate="key",validatecommand=vcmd_pin, text_color="black", width = 210, height = 35, border_width=1, fg_color = "white", font = ("Arial", 20))
reg_pin_entry.place(x = 460, y = 400)

register_btn = CTkButton(register_frame, text = "Register", text_color="white", font=("Arial", 15), width = 370, height = 35, fg_color="Blue", command = register)
register_btn.place(x = 460, y = 500)

#Log in Account 
login_num_entry = CTkEntry(log_in_frame, validate="key",validatecommand=vcmd, text_color="black", width = 370, height = 35, border_width=1, fg_color = "white", font =("Arial", 20))
login_num_entry.place(x = 460, y = 300)
login_pin_entry = CTkEntry(log_in_frame, validate="key",validatecommand=vcmd_pin, text_color="black", width = 210, height = 35, border_width=1, fg_color = "white", font = ("Arial", 20))
login_pin_entry.place(x = 460, y = 400)

login_btn = CTkButton(log_in_frame, text = "Log In", text_color="white", font=("Arial", 15), width = 370, height = 35, fg_color="Blue", command = login)
login_btn.place(x = 460, y = 500)

clicked_reg_btn = CTkLabel(register_frame, text = "REGISTER", corner_radius=5, fg_color="#2f4ead", font=("Arial", 20), width=180)
clicked_reg_btn.place(x = 450, y = 150)
to_reg_btn = CTkButton(log_in_frame, text = "REGISTER", text_color="Black", hover_color="#2f4ead", fg_color="lightblue", font=("Arial", 20), width = 180, command = switch_to_reg)
to_reg_btn.place(x = 450, y = 150)

clicked_login_btn = CTkLabel(log_in_frame, text = "LOG IN", corner_radius=5, fg_color="#2f4ead", font=("Arial", 20), width=180)
clicked_login_btn.place(x = 650, y = 150)
to_login_btn = CTkButton(register_frame, text = "LOG IN", text_color="Black", hover_color="#2f4ead", fg_color="lightblue", font=("Arial", 20), width = 180, command = switch_to_login)
to_login_btn.place(x = 650, y = 150)


register_frame.pack(expand = 1, fill = BOTH)

root.mainloop() 

Python Online Compiler

Write, Run & Share Python code online using OneCompiler's Python online compiler for free. It's one of the robust, feature-rich online compilers for python language, supporting both the versions which are Python 3 and Python 2.7. Getting started with the OneCompiler's Python editor is easy and fast. The editor shows sample boilerplate code when you choose language as Python or Python2 and start coding.

Taking inputs (stdin)

OneCompiler's python online editor supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample python program which takes name as input and print your name with hello.

import sys
name = sys.stdin.readline()
print("Hello "+ name)

About Python

Python is a very popular general-purpose programming language which was created by Guido van Rossum, and released in 1991. It is very popular for web development and you can build almost anything like mobile apps, web apps, tools, data analytics, machine learning etc. It is designed to be simple and easy like english language. It's is highly productive and efficient making it a very popular language.

Tutorial & Syntax help

Loops

1. If-Else:

When ever you want to perform a set of operations based on a condition IF-ELSE is used.

if conditional-expression
    #code
elif conditional-expression
    #code
else:
    #code

Note:

Indentation is very important in Python, make sure the indentation is followed correctly

2. For:

For loop is used to iterate over arrays(list, tuple, set, dictionary) or strings.

Example:

mylist=("Iphone","Pixel","Samsung")
for i in mylist:
    print(i)

3. While:

While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.

while condition  
    #code 

Collections

There are four types of collections in Python.

1. List:

List is a collection which is ordered and can be changed. Lists are specified in square brackets.

Example:

mylist=["iPhone","Pixel","Samsung"]
print(mylist)

2. Tuple:

Tuple is a collection which is ordered and can not be changed. Tuples are specified in round brackets.

Example:

myTuple=("iPhone","Pixel","Samsung")
print(myTuple)

Below throws an error if you assign another value to tuple again.

myTuple=("iPhone","Pixel","Samsung")
print(myTuple)
myTuple[1]="onePlus"
print(myTuple)

3. Set:

Set is a collection which is unordered and unindexed. Sets are specified in curly brackets.

Example:

myset = {"iPhone","Pixel","Samsung"}
print(myset)

4. Dictionary:

Dictionary is a collection of key value pairs which is unordered, can be changed, and indexed. They are written in curly brackets with key - value pairs.

Example:

mydict = {
    "brand" :"iPhone",
    "model": "iPhone 11"
}
print(mydict)

Supported Libraries

Following are the libraries supported by OneCompiler's Python compiler

NameDescription
NumPyNumPy python library helps users to work on arrays with ease
SciPySciPy is a scientific computation library which depends on NumPy for convenient and fast N-dimensional array manipulation
SKLearn/Scikit-learnScikit-learn or Scikit-learn is the most useful library for machine learning in Python
PandasPandas is the most efficient Python library for data manipulation and analysis
DOcplexDOcplex is IBM Decision Optimization CPLEX Modeling for Python, is a library composed of Mathematical Programming Modeling and Constraint Programming Modeling