import telepot #wrapper for telegram

import time 

import datetime #to get unix timing

import requests #make our life easier getting data from api

import json #required to decode the API data

from telepot.loop import MessageLoop 

from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton

import schedule # for the alarm function, i.e scheduling of timings to alert user



#defining variables

xc = 0

amt = []

TOKEN = "410139836:AAEOLl72--ZUt-yOKX215fq1vWcjMlTODkQ" #token from FATHER OF ALL BOTS

bot = telepot.Bot(TOKEN)







#class creation to properly contain all data

class bot():



    #creates global variable that can be used throughout the python programme

    def create_global_variable():

       

        global currency

        global amt

        

        currency = str('')

    #the start of the program, command handler for /start to start program

    def handle(msg): #handles quickly recieve messages from the user

        chat_id = msg['chat']['id']

        command = msg['text']

        

        if command == '/start': 

            bot.sendMessage(chat_id, "I AM MUTHU THE MONEY CHANGER BOT! \U0001f473\U0001f3fe") #no offence/racism in play, just a name

            keyboard = InlineKeyboardMarkup(inline_keyboard=[

                           [InlineKeyboardButton(text='Convert Currency \U0001f4b1', callback_data='convert')], #pathway to convert and calculate money

                           [InlineKeyboardButton(text='Analyse Currency \U0001f4b9', callback_data='analyse')]  #analyse the trend of the currency 

                        ])

            bot.sendMessage(chat_id, "Select the following: Convert or \nTrack currency and set a timer for tomorrow!", reply_markup=keyboard)

        else:

            bot.sendMessage(chat_id, "Please press /start to begin") #Make sure that the user gives the correct input(edge checking!)

            

       

       

    #functions to be executed when convert/analyse is input

    def on_callback_query(msg):



        global xc

        

        query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')

    

        print('Callback Query2:', query_id, from_id, query_data)

        



        #callback data is formatted into query_data using telepot.glance

        #when the input is detected as convert, the inline keyboard containing all the possible currency from fixer.io will be give to the user to choose

        if query_data == 'convert':

            bot.sendMessage(from_id, "Wait ah bro!\nFinding the rates for you... \U0001f468\U0001f3fe\U0000200d\U0001f4bb") #emoji included to interact with user

            keyboard = InlineKeyboardMarkup(inline_keyboard=[

                       [InlineKeyboardButton(text='AUD \U0001f1e6\U0001f1fa', callback_data='AUD'),

                       InlineKeyboardButton(text='BGN \U0001f1e7\U0001f1ec', callback_data='BGN'),

                       InlineKeyboardButton(text='BRL \U0001f1e7\U0001f1f7', callback_data='BRL')],

                       [InlineKeyboardButton(text='CAD \U0001f1e8\U0001f1e6', callback_data='CAD'),

                       InlineKeyboardButton(text='CHF \U0001f1e8\U0001f1ed', callback_data='CHF'),

                       InlineKeyboardButton(text='CNY \U0001f1e8\U0001f1f3', callback_data='CNY')],

                       [InlineKeyboardButton(text='CZK \U0001f1e8\U0001f1ff', callback_data='CZK'),

                       InlineKeyboardButton(text='DKK \U0001f1e9\U0001f1f0', callback_data='DKK'),

                       InlineKeyboardButton(text='EUR \U0001f1ea\U0001f1fa', callback_data='EUR')],

                       [InlineKeyboardButton(text='GBP \U0001f1ec\U0001f1e7', callback_data='GBP'),

                       InlineKeyboardButton(text='HKD \U0001f1ed\U0001f1f0', callback_data='HKD'),

                       InlineKeyboardButton(text='HRK \U0001f1ed\U0001f1f7', callback_data='HRK')],

                       [InlineKeyboardButton(text='HUF \U0001f1ed\U0001f1fa', callback_data='HUF'),

                       InlineKeyboardButton(text='IDR \U0001f1ee\U0001f1e9', callback_data='IDR'),

                       InlineKeyboardButton(text='ILS \U0001f1ee\U0001f1f1', callback_data='ILS')],

                       [InlineKeyboardButton(text='INR \U0001f1ee\U0001f1f3', callback_data='INR'),

                       InlineKeyboardButton(text='JPY \U0001f1ef\U0001f1f5', callback_data='JPY'),

                       InlineKeyboardButton(text='KRW \U0001f1f0\U0001f1f7', callback_data='KRW')],

                       [InlineKeyboardButton(text='MXN \U0001f1f2\U0001f1fd', callback_data='MXN'),

                       InlineKeyboardButton(text='MYR \U0001f1f2\U0001f1fe', callback_data='MYR'),

                       InlineKeyboardButton(text='NOK \U0001f1f3\U0001f1f4', callback_data='NOK')],

                       [InlineKeyboardButton(text='NZD \U0001f1f3\U0001f1ff', callback_data='NZD'),

                       InlineKeyboardButton(text='PHP \U0001f1f5\U0001f1ed', callback_data='PHP'),

                       InlineKeyboardButton(text='PLN \U0001f1f5\U0001f1f1', callback_data='PLN')],

                       [InlineKeyboardButton(text='RON \U0001f1f7\U0001f1f4', callback_data='RON'),

                       InlineKeyboardButton(text='RUB \U0001f1f7\U0001f1fa', callback_data='RUB'),

                       InlineKeyboardButton(text='SEK \U0001f1f8\U0001f1ea', callback_data='SEK')],

                       [InlineKeyboardButton(text='THB \U0001f1f9\U0001f1ed', callback_data='THB'),

                       InlineKeyboardButton(text='TRY \U0001f1f9\U0001f1f7', callback_data='TRY'),

                       InlineKeyboardButton(text='USD \U0001f1fa\U0001f1f8', callback_data='USD')],

                       [InlineKeyboardButton(text='ZAR \U0001f1ff\U0001f1e6', callback_data='ZAR')],

                    ])

            bot.sendMessage(from_id,"OK! Choose from the list of Currency!",reply_markup=keyboard)

        #the elif loop is to check if the input is from the correct inline keyboard.

        elif query_data in ['USD', 'ZAR', 'AUD', 'BGN', 'BRL', 'CAD', 'CHF', 'CNY', 'CZK', 'DKK', 'EUR', 'GBP'

                          ,'HKD', 'HRK', 'HUF', 'IDR', 'ILS', 'INR', 'JPY', 'KRW', 'MXN', 'MYR', 'NOK', 'NZD',

                          'PHP', 'PLN', 'RON', 'RUB', 'SEK', 'THB', 'TRY']:

            #define symbols as a global variable as it will be used again later outside the loop

            global symbols

            #converting data type of query_data to string, just in-case the symbols is wrongly given somehow and crashes the bot

            symbols = str(query_data) 

            #print to make sure that the symbols are correct

            print ("symbols is: ", symbols)

            

            #The website API, fixer.io, provides the exchange rates

            url = "http://api.fixer.io/latest?base=SGD&symbols=" + str(symbols)

            #requests gets us the data available at that particular url

            response = requests.get(url)

            #storing the json info into a variable

            data = response.text 

            #fixer.io gives data in json format and needs to be translated to a python object so we can manipulate it

            #decoding json from the info stored in data

            parsed = json.loads(data)

            #getting only the rates, discarding all other dates etc..

            rates = parsed['rates'] 

            print(rates)

            #removing the chunk of {} and "": using "for" loops to reiterate every character from the string

            #and output only what is needed

            for currency, rate in rates.items():

                print("For SGD = $1 you get {} = ${}".format(currency,rate))

                #storing the extracted value rate into variable called y and xc.

                #two different variable used to reduce confusion because y is used as a "local" variable for this elif loop

                #while xc is used as the global variable which will be referred to outside of this loop

                y=rate 

                xc=rate

                print("xc = ",xc)

                #passing the data we got to the user on telegram

            bot.sendMessage(from_id, "Current Rates: S$1 = {} {}".format(symbols, str(y))) 





            #calculator numpad like no other

            numpad = InlineKeyboardMarkup(inline_keyboard=[

                [InlineKeyboardButton(text='1', callback_data= '1'),

                InlineKeyboardButton(text='2', callback_data= '2'),

                InlineKeyboardButton(text='3', callback_data= '3')],

                [InlineKeyboardButton(text='4', callback_data= '4'),

                InlineKeyboardButton(text='5', callback_data= '5'),

                InlineKeyboardButton(text='6', callback_data= '6')],

                [InlineKeyboardButton(text='7', callback_data= '7'),

                InlineKeyboardButton(text='8', callback_data= '8'),

                InlineKeyboardButton(text='9', callback_data='9')],

                [InlineKeyboardButton(text='0', callback_data='0'),

                 InlineKeyboardButton(text='ENTER', callback_data='done')],

                                   ])

            #asking how much of SGD he/she wants to exchange to his selected currency

            bot.sendMessage(from_id, 'How much do you wanna change bro?', reply_markup=numpad)



            #making sure that it is the numbers that is given

        elif query_data in ['1','2','3','4','5','6','7','8','9','0']:

            #convert query_data to a list so that it can be added into the array

            list(query_data)

            #adding the listed query_data to the empty array 'amt' declared earlier on

            amt.append(query_data)

            #showing the amount that the user gave to him/her

            bot.answerCallbackQuery(query_id, text="$%s?" %(''.join(amt)))



            #this code is to run only when the user is done with inputting the amount they are done and presses the inline button 'enter'

        elif query_data in ['done']:

            bot.sendMessage(from_id, "So you confirm wanna change $%s?" %(''.join(amt)))

            print (int("".join(map(str,amt))))

            #to combine all the arrarys created from above into a single array

            query_data = int("".join(map(str,amt)))

            #some math magic (multiplication of the rates and the amount the use input from previously)

            query_data = xc*query_data

            #print to make sure that the query_data and symbols is still the same as per above

            print (query_data)

            print (symbols)

            #sending the message to user with the amount with 2 decimal points. Have to declare the variable inside {} if not there will be value error

            bot.sendMessage(from_id, "You will recieve {s} {f:.2f}!".format(s=symbols, f=query_data))

            #clear the array so that it can be reused again

            del amt[:]



            #AlWAYS BE KIND!!!

            bot.sendMessage(from_id, "Still want to change money ah bro? \nThen press /start \n Have a nice Day! \nWe hope you enjoyed our service \nPlease vote for us! Thank you very much!!")             

            

        #callback_data modified so as to not conflict with above

        elif query_data == 'analyse':

            keyboard = InlineKeyboardMarkup(inline_keyboard=[

                       [InlineKeyboardButton(text='AUD \U0001f1e6\U0001f1fa', callback_data='AUD1'),

                       InlineKeyboardButton(text='BGN \U0001f1e7\U0001f1ec', callback_data='BGN1'),

                       InlineKeyboardButton(text='BRL \U0001f1e7\U0001f1f7', callback_data='BRL1')],

                       [InlineKeyboardButton(text='CAD \U0001f1e8\U0001f1e6', callback_data='CAD1'),

                       InlineKeyboardButton(text='CHF \U0001f1e8\U0001f1ed', callback_data='CHF1'),

                       InlineKeyboardButton(text='CNY \U0001f1e8\U0001f1f3', callback_data='CNY1')],

                       [InlineKeyboardButton(text='CZK \U0001f1e8\U0001f1ff', callback_data='CZK1'),

                       InlineKeyboardButton(text='DKK \U0001f1e9\U0001f1f0', callback_data='DKK1'),

                       InlineKeyboardButton(text='EUR \U0001f1ea\U0001f1fa', callback_data='EUR1')],

                       [InlineKeyboardButton(text='GBP \U0001f1ec\U0001f1e7', callback_data='GBP1'),

                       InlineKeyboardButton(text='HKD \U0001f1ed\U0001f1f0', callback_data='HKD1'),

                       InlineKeyboardButton(text='HRK \U0001f1ed\U0001f1f7', callback_data='HRK1')],

                       [InlineKeyboardButton(text='HUF \U0001f1ed\U0001f1fa', callback_data='HUF1'),

                       InlineKeyboardButton(text='IDR \U0001f1ee\U0001f1e9', callback_data='IDR1'),

                       InlineKeyboardButton(text='ILS \U0001f1ee\U0001f1f1', callback_data='ILS1')],

                       [InlineKeyboardButton(text='INR \U0001f1ee\U0001f1f3', callback_data='INR1'),

                       InlineKeyboardButton(text='JPY \U0001f1ef\U0001f1f5', callback_data='JPY1'),

                       InlineKeyboardButton(text='KRW \U0001f1f0\U0001f1f7', callback_data='KRW1')],

                       [InlineKeyboardButton(text='MXN \U0001f1f2\U0001f1fd', callback_data='MXN1'),

                       InlineKeyboardButton(text='MYR \U0001f1f2\U0001f1fe', callback_data='MYR1'),

                       InlineKeyboardButton(text='NOK \U0001f1f3\U0001f1f4', callback_data='NOK1')],

                       [InlineKeyboardButton(text='NZD \U0001f1f3\U0001f1ff', callback_data='NZD1'),

                       InlineKeyboardButton(text='PHP \U0001f1f5\U0001f1ed', callback_data='PHP1'),

                       InlineKeyboardButton(text='PLN \U0001f1f5\U0001f1f1', callback_data='PLN1')],

                       [InlineKeyboardButton(text='RON \U0001f1f7\U0001f1f4', callback_data='RON1'),

                       InlineKeyboardButton(text='RUB \U0001f1f7\U0001f1fa', callback_data='RUB1'),

                       InlineKeyboardButton(text='SEK \U0001f1f8\U0001f1ea', callback_data='SEK1')],

                       [InlineKeyboardButton(text='THB \U0001f1f9\U0001f1ed', callback_data='THB1'),

                       InlineKeyboardButton(text='TRY \U0001f1f9\U0001f1f7', callback_data='TRY1'),

                       InlineKeyboardButton(text='USD \U0001f1fa\U0001f1f8', callback_data='USD1')],

                       [InlineKeyboardButton(text='ZAR \U0001f1ff\U0001f1e6', callback_data='ZAR1')],

                    ])

            bot.sendMessage(from_id, "What is your preferred currency",reply_markup=keyboard)

        

        elif query_data in ['USD1', 'ZAR1', 'AUD1', 'BGN1', 'BRL1', 'CAD1', 'CHF1', 'CNY1', 'CZK1', 'DKK1', 'EUR1', 'GBP1'

                          ,'HKD1', 'HRK1', 'HUF1', 'IDR1', 'ILS1', 'INR1', 'JPY1', 'KRW1', 'MXN1', 'MYR1', 'NOK1', 'NZD1',

                          'PHP1', 'PLN1', 'RON1', 'RUB1', 'SEK1', 'THB1', 'TRY1']:

            symbols = str(query_data)

            print(symbols[0:4])

            #getting rate from 7 days ago

            

            #variable z is the date 7 days ago

            #A Unix epoch timestamp can be converted to a datetime object by using the datetime.datetime.fromtimestamp() function

            #passing time.time() into datetime function returns the current unix timming

            #so by deducting a week's (60*60*24*7) seconds we get the date of 7 days ago which is 1 week from the current day.

            z = str(datetime.datetime.fromtimestamp(time.time()-(60*60*24*7)))

            #make use of the fact that fixer.io records all the historical rates,

            #we can easily get the rates from exactly a week ago as long as we have the date

            #This also saves us the hassle to cerate a database and store the data on our own which can be taxing for the bot

            #make use of slicing of strings so that only the correct data gets into the url string

            url = "http://api.fixer.io/{}?base=SGD&symbols={}".format(z[0:10],symbols[0:4])

            response = requests.get(url)

            data = response.text

            parsed = json.loads(data)

            rates = parsed['rates']

            print(rates)



            for currency, rate in rates.items():

                week = rate

            

            #getting current day's rate   

            url2 = "http://api.fixer.io/latest?base=SGD&symbols={}".format(symbols[0:4])

            response2 = requests.get(url2)

            data2 = response2.text

            parsed2 = json.loads(data2)

            ratesnew = parsed2['rates']

            print(ratesnew)

            for currency, ratenew in ratesnew.items():

                print("For SGD = $1 you get {} = ${}".format(currency,ratenew))

                ynew = ratenew

            #formula to get percentage change from last week compared to today

            percentagechange1 = ((ynew - week)/(week))*100

        

                

       

            #defining getting current's day rate and the day before's rate as seperate function

            #This function is to be called by the schedule function later so that

            #when the bot alerts the user, the bot will be immediately fetch the rates from the same country that the user previously selected

            #saves them the hassle and trouble to reselect and go through the steps again

            def job1():

                #getting the day's before rate relative to current day.

                z = str(datetime.datetime.fromtimestamp(time.time()-(60*60*24*1)))

                url = "http://api.fixer.io/{}?base=SGD&symbols={}".format(z[0:10],symbols[0:4])

                response = requests.get(url)

                data = response.text

                parsed = json.loads(data)

                rates = parsed['rates']

                print(rates)



                for currency, rate in rates.items():

                    yold = rate

            

            #getting current day's rate   

                url2 = "http://api.fixer.io/latest?base=SGD&symbols={}".format(symbols[0:4])

                response2 = requests.get(url2)

                data2 = response2.text

                parsed2 = json.loads(data2)

                ratesnew = parsed2['rates']

                print(ratesnew)

                for currency, ratenew in ratesnew.items():

                    print("For SGD = $1 you get {} = ${}".format(currency,ratenew))

                    ynew = ratenew

            #formula to get percentage change from yesterday compared to today

                percentagechange = ((ynew - yold)/(yold))*100

                bot.sendMessage(from_id, "Today's rates: {} \n Yesterday's rates: {} \nThe currency changed by {:.10g}% since yesterday".format(ynew, yold, percentagechange))



            #Inline keyboard for them to input their choice if they want to set or continue the alert function

                redo = InlineKeyboardMarkup(inline_keyboard=[

                [InlineKeyboardButton(text='Yes', callback_data= 'yes'),

                InlineKeyboardButton(text= 'No', callback_data= 'no')]

                                   ])

                bot.sendMessage(from_id, "Last week's rates: {} \nThe currency changed by {:.10g}% since last week".format(week, percentagechange1))

            #calling up the inline keyboard redo, to answer for the alarm question.

                bot.sendMessage(from_id, "Would you like to receive an update in 24 hours?",reply_markup=redo)



            

                

            #initiating the function "job1()" first as it is not automatically initiated with messageloop function as it shouldn't be looped in the first place

            #if not initiated there will be a referencing error where schedule called the function first before it is even initiated

            job1()

            #schedule will be initited and will start counting the 24hours as soon as the user presses 'YES' from above.

            #This schedule is give the name 'remind' so that is can be referenced to be cleared later on when the user choose to cancel the alert function

            schedule.every(24).hours.do(job1).tag('remind')

            

        elif query_data == 'yes':

            bot.sendMessage(from_id, "Steady! Scheduled for you already. See ya tomorrow!")

            #friendly reminder to the user

            bot.answerCallbackQuery(query_id, text="Rates don't change on weekends! Bot rests too! :)")

            

        else :

            #when the user presses no, the schedule function named 'remind' will be cancelled 

            bot.sendMessage(from_id, "Byebye! and have a nice day!")

            schedule.clear('remind')



    #Loops the functions and runs the bot        

    MessageLoop(bot, {'chat': handle,'callback_query': on_callback_query}).run_as_thread()

    print('Listening ...')



    #Make sure the bot is reusable, and not stop after one cycle.

    while 1:

        time.sleep(10)

        schedule.run_pending()



    #end of code



        

