import base64
import datetime
from pyodide.ffi import create_proxy, to_js
from js import FileReader, URL, Blob, document
import js
from pyscript import document, when
from models.SQL import (Account, Event, RecurringEvent, session,
                        openDatabase, saveDatabase)
from filesystem import openFromIDB
from Tabs import AccountTab, EventTab, RecurringEventTab, CalendarTab


accountsTab = AccountTab()
eventsTab = EventTab()
recurringEventsTab = RecurringEventTab()
calendarTab = CalendarTab()


def upload_handler(event):
    files = event.target.files
    for file in files:
        reader = FileReader.new()
        reader.onload = create_proxy(onload_handler)
        reader.readAsDataURL(file)


def onload_handler(event):
    file = event.target.result

    with open('current.db', 'wb') as f:
        file = file.removeprefix('data:application/octet-stream;base64,')
        f.write(base64.b64decode(file))
    js.emitEvent('databaseUpdated', selector='body')
    showNoUnsavedChanges()


def download_handler(event=None):
    saveDatabase('current.db')
    dummy = document.createElement('a')
    dummy.download = 'Cashflow Calendar.db'
    with open('current.db', 'rb') as f:
        blob = Blob.new([to_js(f.read())])
        dummy.href = URL.createObjectURL(blob)

        dummy.click()


def importButton(event=None):
    dummy = document.createElement('input')
    dummy.type = 'file'
    dummy.accept = '.db'
    dummy.onchange = create_proxy(upload_handler)
    # Chrome doesn't like when the element isn't in DOM
    dummy.style.display = 'none'
    document.body.appendChild(dummy)
    dummy.click()
    document.getElementById('current-file').value = ''
    document.getElementById('current-file').text = 'None'


def newFile(event=None):
    openDatabase('empty.db')
    showNoUnsavedChanges()
    document.getElementById('current-file').value = ''
    document.getElementById('current-file').text = 'None'


@when("databaseUpdated", selector="body")
async def openFromDisk(event=None):
    openDatabase('current.db')
    js.emitEvent('accountTableModified')
    showNoUnsavedChanges()
    document.getElementById('calendar-tab').click()
    return


def showNoUnsavedChanges(*args):
    document.getElementById('unsaved').classList.remove('d-flex')
    message = f'Last saved: {datetime.datetime.now().strftime("%I:%M%p")}'
    document.getElementById('last-save-time').innerHTML = message
    document.getElementById('no-unsaved').classList.add('d-flex')


@when("click", selector="#open-sample")
def openSample(event=None):
    newFile()
    checking = Account(name='Checking', starting_value=1000,
                       alert_level=0, warn_level=500)
    savings = Account(name='Savings', starting_value=10000,
                      alert_level=1000, warn_level=15000)
    session.add(checking)
    session.add(savings)
    session.commit()
    initEvent1 = Event('Initialize', checking.id,
                       datetime.date(1, 1, 1), 1000, category='init')
    initEvent2 = Event('Initialize', savings.id,
                       datetime.date(1, 1, 1), 10000, category='init')
    session.add(initEvent1)
    session.add(initEvent2)
    session.commit()

    today = datetime.date.today()
    end = today.replace(month=12, day=31)
    if today.month < 11:
        end = end.replace(year=today.year+1)
    recurring = []
    recurring.append(RecurringEvent(name='Paycheck', start=today.replace(
        day=12), end=end, amount=1500, frequency='Weekly', increment=2, account=checking.id))
    recurring.append(RecurringEvent(name='Rent', start=today.replace(
        day=1), end=end, amount=-1000, frequency='Monthly', account=checking.id))
    recurring.append(RecurringEvent(name='Credit Card', start=today.replace(
        day=18), end=end, amount=-250, frequency='Monthly', account=checking.id))
    recurring.append(RecurringEvent(name='Monthly Savings', start=today.replace(
        day=15), end=end, amount=-500, frequency='Monthly', account=checking.id, to_account=savings.id))
    recurring.append(RecurringEvent(name='Car Insurance', start=today.replace(
        month=today.month+1, day=1), end=end, amount=-1000, frequency='Monthly', increment=6, account=checking.id))
    for event in recurring:
        session.add(event)
    session.commit()
    for event in recurring:
        event.generateEvents()

    event = Event(name='Birthday Gifts', date=today.replace(
        month=12, day=25), amount=-100, from_account=checking.id)
    session.add(event)
    session.commit()

    e = session.query(Event).filter(Event.name == 'Credit Card').filter(
        Event.category != 'init').first()
    e.amount = -413.87
    e.override = True
    session.commit()
    js.emitEvent('accountTableModified')
    js.emitEvent('eventTableModified')
    js.emitEvent('recurringEventTableModified')
    
    document.getElementById('calendar-tab').click()

document.getElementById('new-file').onclick = newFile
document.getElementById('download').onclick = download_handler
document.getElementById('import').onclick = importButton
document.getElementById('current-file').value = ''


def getAccountsForDropdown(*ags):
    accounts = session.query(Account).all()
    return to_js({a.id: a.name for a in accounts})

def getAccountTable(*args):
    rows, columns = accountsTab.fetch()
    return to_js([rows, columns])

def getEventTable(*args):
    rows, columns = eventsTab.fetch()
    return to_js([rows, columns])

def getRecurringEventTable(*args):
    rows, columns = recurringEventsTab.fetch()
    return to_js([rows, columns])

def getCalendarTable(includeNoTransactions, *args):
    startDate = document.getElementById('calendar-range-start').value
    startDate = datetime.datetime.strptime(startDate, '%Y-%m-%d')
    endDate = document.getElementById('calendar-range-end').value
    endDate = datetime.datetime.strptime(endDate, '%Y-%m-%d')
    
    rows, columns = calendarTab.fetch(startDate, endDate, includeNoTransactions)
    return to_js([rows, columns])

def addAccount(*args):
    name = document.getElementById('add-account-name').value
    start = document.getElementById('add-account-startBal').value
    warn = document.getElementById('add-account-warnBal').value
    alert = document.getElementById('add-account-alertBal').value
    accountsTab.add(name, start, warn, alert)
    js.emitEvent('accountTableModified')

def addEvent(*args):
    name = document.getElementById('add-event-name').value
    date = document.getElementById('add-event-date').value
    date = datetime.datetime.strptime(date, '%Y-%m-%d').date()
    amount = document.getElementById('add-event-amount').value
    account = document.getElementById('add-event-account').value
    toAccount = document.getElementById('add-event-toAccount').value
    if toAccount == '':
        toAccount = None
    eventsTab.add(name, date, amount, account, toAccount)
    js.emitEvent('eventTableModified')

def addRecurringEvent(*args):
        name = document.getElementById('add-recurring-event-name').value
        start = document.getElementById('add-recurring-event-start').value
        start = datetime.datetime.strptime(start, '%Y-%m-%d').date()
        end = document.getElementById('add-recurring-event-endDate').value
        end = datetime.datetime.strptime(end, '%Y-%m-%d').date()
        amount = document.getElementById('add-recurring-event-amount').value
        account = document.getElementById('add-recurring-event-account').value
        toAccount = document.getElementById('add-recurring-event-toAccount').value
        frequency = document.getElementById('add-recurring-event-frequency').value
        increment = document.getElementById('add-recurring-event-increment').value
        toAccount = document.getElementById('add-recurring-event-toAccount').value
        if toAccount == '':
            toAccount = None
        recurringEventsTab.add(name, start, end, amount, account, frequency, increment, toAccount)
        js.emitEvent('recurringEventTableModified')


js.createObject(create_proxy(Account.deleteById), 'deleteAccount')
js.createObject(create_proxy(Account.setPropertyById), 'setAccountProperty')
js.createObject(create_proxy(Event.deleteById), 'deleteEvent')
js.createObject(create_proxy(Event.setPropertyById), 'setEventProperty')
js.createObject(create_proxy(RecurringEvent.deleteById),
                'deleteRecurringEvent')
js.createObject(create_proxy(RecurringEvent.setPropertyById),
                'setRecurringEventProperty')
js.createObject(create_proxy(getAccountsForDropdown), 'getAccountsForDropdown')
js.createObject(create_proxy(addAccount), 'addAccount')
js.createObject(create_proxy(addEvent), 'addEvent')
js.createObject(create_proxy(addRecurringEvent), 'addRecurringEvent')
js.createObject(create_proxy(getAccountTable), 'getAccountTable')
js.createObject(create_proxy(getEventTable), 'getEventTable')
js.createObject(create_proxy(getRecurringEventTable), 'getRecurringEventTable')
js.createObject(create_proxy(getCalendarTable), 'getCalendarTable')
js.createObject(create_proxy(showNoUnsavedChanges), 'showNoUnsavedChanges')

loadingElements = document.querySelectorAll('.loading')
for element in loadingElements:
    element.classList.remove('loading')

spinner = document.querySelector('.loading-spinner')
spinner.style.display = 'none'
spinner.classList.remove('d-flex')
