#!/usr/bin/python3
# 3/28/2019 Skeetzo
# OnlySnarf.py menu system

### doesn't work:
# upload & backup (requires upload via local added to main script)
# settings menu -> "Incorrect Index"

import random
import os
import shutil
import datetime
import json
import sys
import pathlib
from OnlySnarf.settings import SETTINGS as settings
from OnlySnarf import onlysnarf as OnlySnarf
from OnlySnarf import google as Google

###################
##### Globals #####
###################

version = "1.3.2"
header = "\n ________         .__          _________                     _____ \n \
\\_____  \\   ____ |  | ___.__./   _____/ ____ _____ ________/ ____\\\n \
 /   |   \\ /    \\|  |<   |  |\\_____  \\ /    \\\\__  \\\\_   _ \\   __\\ \n \
/    |    \\   |  \\  |_\\___  |/        \\   |  \\/ __ \\ |  |\\/| |   \n \
\\_______  /___|  /____/ ____/_______  /___|  (____  \\\\__|  |_|   \n \
        \\/     \\/     \\/            \\/     \\/     \\/              \n"

UPDATED = False
UPDATED_TO = False
INITIALIZED = False

colors = {
        'blue': '\033[94m',
        'header': '\033[48;1;34m',
        'teal': '\033[96m',
        'pink': '\033[95m',
        'green': '\033[92m',
        'yellow': '\033[93m',
        'menu': '\033[48;1;44m'
        }

menuItems = []
actionItems = []
messageItems = []
fileItems = []
locationItems = []
promotionItems = []
settingItems = []

def initialize():
    # print("Initializing Menu")
    global INITIALIZED
    if INITIALIZED:
        # print("Already Initialized, Skipping")
        return
    global settingItems
    # Settings Menu
    settingItems = sorted([
        [ "Backup", settings.BACKING_UP, ["True","False"]],
        [ "Delete Google", settings.DELETING, ["True","False"]],
        [ "Delete Local", settings.REMOVE_LOCAL, ["True","False"]],
        [ "Hashtag", settings.HASHTAGGING, ["True","False"]],
        [ "Force Backup", settings.BACKING_UP_FORCE, ["True","False"]],
        [ "Force Upload", settings.FORCE_UPLOAD, ["True","False"]],
        [ "Mount Path", settings.MOUNT_PATH],
        [ "Google: Root Folder Path", settings.MOUNT_DRIVE],
        [ "Users Path", settings.USERS_PATH],
        [ "Show Window", settings.SHOW_WINDOW, ["True","False"]],
        [ "Google: Root Folder Name", settings.ROOT_FOLDER],
        [ "Google: Drive Folders", settings.DRIVE_FOLDERS],
        [ "Image Limit", settings.IMAGE_UPLOAD_LIMIT],
        [ "Image Max", settings.IMAGE_UPLOAD_MAX],
        [ "Tweeting", settings.TWEETING, ["True","False"]],
        [ "Debug", settings.DEBUG, ["True","False"]],
        [ "Debug Skip Download", settings.SKIP_DOWNLOAD, ["True","False"]],    
        [ "Create Missing Google Folders", settings.CREATE_MISSING_FOLDERS, ["True","False"]],    
        [ "Verbal", settings.VERBAL, ["True","False"]]    
    ])
    if str(settings.DEBUG) == "True":
        settingItems.append([ "File Name", settings.FILE_NAME])
        settingItems.append([ "File Path", settings.FILE_PATH])
        settingItems.append([ "Location", settings.LOCATION, ["Local","Google"]])
        settingItems.append([ "Text", settings.TEXT])
        settingItems.append([ "Image", settings.IMAGE])
    settingItems.insert(0,[ "Back", "main"])

    global menuItems
    # Main Menu
    menuItems = [
        [ "Actions", "action"],
        [ "Settings", "set_settings"],
        [ "Exit", "exit"]
    ]

    global actionItems
    # Actions Menu
    actionItems = sorted([
        [ "Release", "release" ],
        [ "Download", "download" ],
        [ "Promotion", "promotion" ],
        [ "Message", "message" ],
        [ "Reset", "reset" ]
    ])
    if str(settings.DEBUG) == "True":
        actionItems.append([ "Test", "test"])
    actionItems.insert(0,[ "Back", "main"])

    global messageItems
    # Message Menu
    messageItems = sorted([
        [ "All", "all"],
        [ "New", "new"],
        [ "Recent", "recent"],
        [ "User by Username", "user"]
    ])
    messageItems.insert(0,[ "Back", "main"])

    global fileItems
    # File Type Menu
    fileItems = sorted([
        [ "Image", "image"],
        [ "Gallery", "gallery"],
        [ "Performer", "performer"],
        [ "Scene", "scene"],
        [ "Video", "video"],
    ])
    fileItems.insert(0,[ "Back", "main"])

    global locationItems
    # File Location Menu
    locationItems = sorted([
        [ "Local", "local"],
        [ "Google Drive", "google"]
    ])
    locationItems.insert(0,[ "Back", "main"])

    global promotionItems
    if str(settings.DEBUG) == "True":
        promotionItems = sorted([
            [ "Enter Email", "email" ],
            # [ "Select User", "select" ]
        ])
    promotionItems.insert(0,[ "Back", "main"])

    # print("Initialized Menu")
    INITIALIZED = True

#####################
##### Functions #####
#####################

### Action Menu - file type
def action():
    for item in actionItems:
        print(colorize("[" + str(actionItems.index(item)) + "] ", 'teal') + list(item)[0])
    while True:
        choice = input(">> ")
        try:
            if int(choice) < 0 or int(choice) >= len(actionItems): raise ValueError
            if str(actionItems[int(choice)][1]) == "main":
                return main()
            elif str(actionItems[int(choice)][1]) == "reset":
                OnlySnarf.remove_local()
            elif str(actionItems[int(choice)][1]) == "message":
                actionChoice = list(actionItems[int(choice)])[1]
                return finalizeMessage(actionChoice)
            elif str(actionItems[int(choice)][1]) == "promotion":
                actionChoice = list(actionItems[int(choice)])[1]
                return finalizePromotion(actionChoice)
            else:
                actionChoice = list(actionItems[int(choice)])[1]
                return finalizeAction(actionChoice)
        except (ValueError, IndexError):
            print("Error: Incorrect Index")
        except Exception as e:
            print(e)
            print("Error: Missing Method") 

### Action Menu - finalize
def finalizeAction(actionChoice):
    for item in fileItems:
        print(colorize("[" + str(fileItems.index(item)) + "] ", 'teal') + list(item)[0])
    while True:
        fileChoice = input(">> ")
        try:
            if int(fileChoice) < 0 or int(fileChoice) >= len(fileItems): raise ValueError
            if str(fileItems[int(fileChoice)][1]) == "main":
                return action()
            # Call the matching function
            fileChoice = list(fileItems[int(fileChoice)])[1]
            return performAction(actionChoice, fileChoice)
        except (ValueError, IndexError):
            print("Error: Incorrect Index")
        except Exception as e:
            print(e)
            print("Error: Missing Method") 

### Action Menu - perform
def performAction(actionChoice, fileChoice):
    try:
        method = getattr(OnlySnarf, str(actionChoice))
        response = method(fileChoice)
        if response:
            if str(actionChoice) == "download":
                for setting in settingItems:
                    if setting[0] == "File Name":
                        setting[1] = response[0]
                    elif setting[0] == "File Path":
                        setting[1] = response[1]
    except (ValueError, IndexError):
        print("Error: Incorrect Index")
    except Exception as e:
        print(e)
        print("Error: Missing Method") 
    mainMenu()

# Message Menu - finalize
def finalizeMessage(actionChoice):
    for item in messageItems:
        print(colorize("[" + str(messageItems.index(item)) + "] ", 'teal') + list(item)[0])
    while True:
        choice = input(">> ")
        try:
            choice = int(choice)
            if int(choice) < 0 or int(choice) >= len(messageItems): raise ValueError
            if str(messageItems[int(choice)][1]) == "main":
                return action()
            return performMessage(actionChoice, messageItems[int(choice)][1])
        except (ValueError, IndexError):
            print(sys.exc_info()[0])
            print("Error: Incorrect Index")

# Message Menu - perform
def performMessage(actionChoice, messageChoice):
    username = None
    if str(messageChoice) == "user":
        users = displayUsers()
        seeking = True
        while seeking:
            choice = input(">> ")
            try:
                if int(choice) < 0 or int(choice) > len(users): raise ValueError
                if int(choice) == 0:
                    return finalizeMessage(actionChoice)
                username = users[int(choice)-1].username
                seeking = False
            except (ValueError, IndexError):
                print(sys.exc_info()[0])
                print("Error: Incorrect Index")
                return mainMenu()
    images = selectImage(messageChoice)
    # [folder , image_file]
    # print("len: " + str(len(images)))
    while True:
        choice = input(">> ")
        try:
            if int(choice) < 0 or int(choice) > len(images): raise ValueError
            if int(choice) == 0:
                return finalizeMessage(actionChoice)
            try:
                image = images[int(choice)-1]
                message(messageChoice, [image[1],image[0]], username)
                return mainMenu()
            # except (ValueError, IndexError):
                # print("Error: Incorrect Index")
            except Exception as e:
                print(e)
                print("Error: Missing Method")
        except (ValueError, IndexError):
            print("Error: Incorrect Index")
    # mainMenu()    

# {
#   image: file
#   folder: folder
# }
def message(choice, image=None, username=None):
    message = input("Message: ")
    waiting = True
    while waiting:
        try:
            price = input("Price: ")
            "{:.2f}".format(float(price))
            waiting = False
        except ValueError:
            print("Enter a currency amount!")
    if not image or not image[0] or image[0] == None:
        print("Error: Missing Image")
        return
    file_path = Google.download_file(image[0])
    successful_message = OnlySnarf.message(choice=choice, message=message, image=file_path, price=price, username=username)
    if successful_message and str(choice) != "new":
        Google.move_file(image[0])
    else:
        print("Error: Failure Messaging")
        return False

# Promotion Menu - finalize
def finalizePromotion(actionChoice):
    for item in promotionItems:
        print(colorize("[" + str(promotionItems.index(item)) + "] ", 'teal') + list(item)[0])
    while True:
        choice = input(">> ")
        try:
            choice = int(choice)
            if int(choice) < 0 or int(choice) > len(promotionItems): raise ValueError
            if str(promotionItems[int(choice)][1]) == "main":
                return action()
            choice = list(promotionItems[int(choice)])[1]
            return performPromotion(actionChoice, choice)
        except (ValueError, IndexError):
            print(sys.exc_info()[0])
            print("Error: Incorrect Index")

def performPromotion(actionChoice, promotionChoice):
    def promote(username):
        if username == None:
            print("Warning: No user found")
        else:
            OnlySnarf.give_trial(username)
        mainMenu()    
    try:
        username = None
        if str(promotionChoice) == "email":
            # prompt
            choice = input("Email: ")
            username = str(choice)
            return promote(username)
        elif str(promotionChoice) == "select":
            users = displayUsers()    
            while True:
                choice = input(">> ")
                try:
                    if int(choice) < 0 or int(choice) > len(users): raise ValueError
                    if int(choice) == 0:
                        return finalizePromotion(actionChoice)
                    return promote(str(users[int(choice)-1].username))

                except (ValueError, IndexError):
                    print(sys.exc_info()[0])
                    print("Error: Incorrect Index")            
    except (ValueError, IndexError):
        print("Error: Incorrect Index")
    except Exception as e:
        print(e)
        print("Error: Missing Method") 
    mainMenu()

# displays and returns users
def displayUsers():
    users = OnlySnarf.get_users()
    print(colorize("[0] ", 'blue') + "Back")
    # show list
    i = 1
    for user in users:
        print(colorize("[" + str(i) + "] ", 'blue') + str(user.username))
        i = i+1
    return users

def selectImage(folderName):
    images = Google.get_images()
    print(colorize("[0] ", 'blue') + "Back")
    i = 1
    for image in images:
        print(colorize("[" + str(i) + "] ", 'blue') + str(image[0]["title"]) + " - " + str(image[1]['title']))
        i = i+1
    return images
    # performMessage -> [folder , image_file] -> performMessage


###########################

### Settings Menu
def set_settings():
    showHeader()
    print(colorize("Set:",'menu'))
    global settingItems
    for item in settingItems:
        print(colorize("[" + str(settingItems.index(item)) + "] ", 'blue') + list(item)[0])
    while True:
        choice = input(">> ")
        try:
            if int(choice) < 0 or int(choice) >= len(settingItems): raise ValueError
            settingChoice = list(settingItems[int(choice)])[0]
            settingValue = list(settingItems[int(choice)])[1]
            if str(settingChoice) == "Back":
                return main()
            elif str(settingChoice) == "File Name":
                settingValue = input("Enter the file name: ")
            elif str(settingChoice) == "File Path":
                settingValue = input("Enter the file path: ")
            elif str(settingChoice) == "Text":
                settingValue = input("Enter the upload text: ")
            elif str(settingChoice) == "Mount Path":
                settingValue = input("Enter the mount path: ")
            elif str(settingChoice) == "Google: Root Folder Path":
                settingValue = input("Enter the drive path (folderName/folderName/...): ")
            elif str(settingChoice) == "Image":
                settingValue = input("Enter the image path: ")
            elif str(settingChoice) == "Google: Root Folder Name":
                settingValue = input("Enter the Google root folder name: ")
            elif str(settingChoice) == "Google: Drive Folders":
                settingValue = input("Enter the Google drive folders (separated by ',', no spaces): ")
                settingValue = settingValue.split(",")
            elif str(settingChoice) == "Image Limit":
                settingValue = input("Enter the image upload limit: ")
            elif str(settingChoice) == "Image Max":
                settingValue = input("Enter the image upload max: ")
            else:
                list_ = list(settingItems[int(choice)][2])
                print(colorize(str(settingChoice)+" =", 'blue'))
                for item in list_:
                    print(colorize("[" + str(list_.index(item)) + "] ", 'pink') + str(item))
                while True:
                    updateChoice = input(">> ")
                    try:
                        if int(updateChoice) < 0 or int(updateChoice) >= len(list(settingItems[int(choice)][2])): raise ValueError
                        settingValue = list_[int(updateChoice)]
                        break
                    except (ValueError, IndexError):
                        print("Incorrect Index")
                    except Exception as e:
                        print('What did shnnarf break?')
                        print(e)
                        break
            global UPDATED
            UPDATED = settingChoice
            global UPDATED_TO
            UPDATED_TO = settingValue
            settingItems[int(choice)][1] = settingValue
            settings.update_value(settingChoice, settingValue)
            return set_settings()
        except (ValueError, IndexError):
            print("Incorrect Index")
        except:
            print(sys.exc_info()[0])
            return main()

###########################

def colorize(string, color):
    if not color in colors: return string
    return colors[color] + string + '\033[0m'
  
def exit():
    print("Shnarrf?")
    sys.exit(0)

###########################
import atexit
def exit_handler():
    print('Shnnarrrff!')
    exit()
atexit.register(exit_handler)

import signal
def signal_handler(sig, frame):
    print('Shnnnarf?')
    exit()
signal.signal(signal.SIGINT, signal_handler)
###########################

def main():
    showHeader()
    mainMenu()

def mainMenu():
    ### Main Menu
    print(colorize("Select an option:", 'menu'))
    for item in menuItems:
        print(colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item)[0])
    while True:
        choice = input(">> ")
        try:
            if int(choice) < 0 or int(choice) >= len(menuItems): raise ValueError
            # Call the matching function
            method_name = list(menuItems[int(choice)])[1]
            possibles = globals().copy()
            possibles.update(locals())
            method = possibles.get(method_name)
            if method is not None:
                return method()
            else:
                print("Missing Option")    
        except (ValueError, IndexError, KeyboardInterrupt):
            print("Incorrect Index")
            pass

def showHeader():
    os.system('clear')
    # Print some badass ascii art header here !
    print(colorize(header, 'header'))
    print(colorize('version '+version+'\n', 'green'))
    showSettings()

def showSettings():
    print('Settings:')
    for setting in settingItems:
        if str(setting[0]) != "Back":
            print(' - '+setting[0]+' = '+str(setting[1]))
    global UPDATED
    global UPDATED_TO
    if str(UPDATED) != "False":
        print('\nUpdated: '+str(UPDATED)+' -> '+str(UPDATED_TO))
    UPDATED = False
    print('\r')

###########################

if __name__ == "__main__":
    try:
        main_other()
    except:
        # print(sys.exc_info()[0])
        print("Shhhhhnnnnnarf!")
    finally:
        sys.exit(0)

def main_other():
    settings.initialize()
    initialize()
    main()