# Path: budgettracker/helpers.py
# def load_config(filename=CONFIG_FILENAME):
#     config = {}
#     if os.path.exists(filename):
#         with open(filename) as f:
#             config = yaml.load(f)
#     config = {k.lower(): v for k, v in config.items()}
#     for k, v in os.environ.items():
#         if k.startswith('BUDGET_') and k != 'BUDGET_CONFIG':
#             config[k[7:].lower()] = v
#     return config
# 
# def update_local_data(config, notify=True, date=None, storage=None, adapter=None, filename=None, reset=False):
#     if not adapter:
#         adapter = get_bank_adapter_from_config(config, filename)
#     if not storage:
#         storage = get_storage_from_config(config)
# 
#     if not date:
#         if datetime.date.today().day <= 5:
#             # if we are still in the early days of a new month, keep updating the previous month
#             update_local_data(config, False, datetime.date.today() - monthdelta(1), adapter, session)
#         date = datetime.date.today().replace(day=1)
#     elif date < datetime.date.today().replace(day=1):
#         notify = False
# 
#     prev_budget = load_monthly_budget_from_config(config, date, storage)
# 
#     update_monthly_transactions(storage, adapter, date, reset)
#     update_accounts(storage, adapter, reset)
# 
#     budget = load_monthly_budget_from_config(config, date, storage)
# 
#     if notify:
#         if config.get('notify_remaining') and prev_budget.expected_remaining > config['notify_remaining'] and budget.expected_remaining <= config['notify_remaining']:
#             notify_using_config(config, 'BUDGET: /!\ LOW SAFE TO SPEND: %s' % budget.expected_remaining)
#         elif config.get('notify_delta') and (prev_budget.expected_remaining - budget.expected_remaining) > config['notify_delta']:
#             notify_using_config(config, 'BUDGET: Remaining funds: %s' % budget.expected_remaining)
# 
#         categories = compute_monthly_categories_from_config(config, date, storage)
#         for category in categories:
#             if category.has_warning:
#                 notify_using_config(config, 'BUDGET: /!\ CATEGORY WARNING: %s (%s / %s)' % (
#                     category.name, category.amount, category.warning_threshold))
# 
# def load_yearly_budgets_from_config(config, date, compute_budget_goals=True, storage=None):
#     if not storage:
#         storage = get_storage_from_config(config)
#     start_date = date.replace(day=1, month=1)
#     end_date = start_date.replace(year=start_date.year+1)
#     if start_date.year <= datetime.date.today().year:
#         end_date = min(datetime.date.today().replace(day=1) + monthdelta(1), end_date)
# 
#     transactions = storage.load_yearly_transactions(date)
#     if config.get('income_delay'):
#         transactions.extend(storage.load_monthly_transactions(end_date))
# 
#     return budgetize_from_config(config, transactions, start_date, end_date, compute_budget_goals)
# 
# def notify_using_config(config, message):
#     print message
#     if config.get('notify_adapter'):
#         adapter = import_module('budgettracker.notify_adapters.' + config['notify_adapter'])
#         adapter.send(config, message)
# 
# def compute_yearly_budget_goals_from_config(config, date, storage=None, debug=False):
#     return compute_budget_goals(
#         load_yearly_budgets_from_config(config, date, False, storage),
#         map(BudgetGoal.from_dict, config.get('budget_goals', [])),
#         debug=debug
#     )
# 
# def compute_monthly_categories_from_config(config, date, storage=None):
#     if not storage:
#         storage = get_storage_from_config(config)
#     categories = map(Category.from_dict, config.get('categories', []))
#     transactions = storage.load_monthly_transactions(date)
#     return compute_categories(transactions, categories)
# 
# def rematch_categories(config, storage=None):
#     if not storage:
#         storage = get_storage_from_config(config)
#     categories = map(Category.from_dict, config.get('categories', []))
#     def iterator(tx):
#         return tx.update(
#             categories=list(set(tx.categories or []) | set(match_categories(categories, tx.label))))
#     storage.iter_all_transactions_for_update(iterator)
# 
# def get_storage_from_config(config):
#     return get_storage(config.get('storage', 'csv'))(config)
# 
# def create_amount_formatter(config):
#     def formatter(amount, show_sign=False):
#         sign = ''
#         if show_sign or amount < 0:
#             sign = '+' if amount >= 0 else '-'
#             amount = abs(amount)
#         return config.get('amount_format', '{sign}${amount:.2f}').format(sign=sign, amount=amount)
#     return formatter
# 
# Path: budgettracker/storage.py
# def get_storage(name):
#     for o in globals().values():
#         if inspect.isclass(o) and issubclass(o, StorageBase) and o is not StorageBase and o.name == name:
#             return o


from .helpers import (load_config, update_local_data, load_yearly_budgets_from_config, notify_using_config,
                      compute_yearly_budget_goals_from_config, compute_monthly_categories_from_config,
                      rematch_categories, get_storage_from_config, create_amount_formatter)
from .storage import get_storage
from getopt import getopt
    from .web import app
import datetime, sys, os, json
# -*- coding: utf-8 -*-


config = load_config()
storage = get_storage_from_config(config)
famount = create_amount_formatter(config)
commands = {}


def command(options='', long_options=None):
    def decorator(func):
        commands[func.__name__] = (func, options, long_options or [])
        return func
    return decorator


@command('', ['month=', 'year=', 'reset'])
def update(filename=None, month=None, year=None, reset=False):
    date = None
    if month or year:
        if not month:
            month = datetime.date.today().month
        if not year:
            year = datetime.date.today().year

# Path: budgettracker/helpers.py
# def load_config(filename=CONFIG_FILENAME):
#     config = {}
#     if os.path.exists(filename):
#         with open(filename) as f:
#             config = yaml.load(f)
#     config = {k.lower(): v for k, v in config.items()}
#     for k, v in os.environ.items():
#         if k.startswith('BUDGET_') and k != 'BUDGET_CONFIG':
#             config[k[7:].lower()] = v
#     return config
# 
# def update_local_data(config, notify=True, date=None, storage=None, adapter=None, filename=None, reset=False):
#     if not adapter:
#         adapter = get_bank_adapter_from_config(config, filename)
#     if not storage:
#         storage = get_storage_from_config(config)
# 
#     if not date:
#         if datetime.date.today().day <= 5:
#             # if we are still in the early days of a new month, keep updating the previous month
#             update_local_data(config, False, datetime.date.today() - monthdelta(1), adapter, session)
#         date = datetime.date.today().replace(day=1)
#     elif date < datetime.date.today().replace(day=1):
#         notify = False
# 
#     prev_budget = load_monthly_budget_from_config(config, date, storage)
# 
#     update_monthly_transactions(storage, adapter, date, reset)
#     update_accounts(storage, adapter, reset)
# 
#     budget = load_monthly_budget_from_config(config, date, storage)
# 
#     if notify:
#         if config.get('notify_remaining') and prev_budget.expected_remaining > config['notify_remaining'] and budget.expected_remaining <= config['notify_remaining']:
#             notify_using_config(config, 'BUDGET: /!\ LOW SAFE TO SPEND: %s' % budget.expected_remaining)
#         elif config.get('notify_delta') and (prev_budget.expected_remaining - budget.expected_remaining) > config['notify_delta']:
#             notify_using_config(config, 'BUDGET: Remaining funds: %s' % budget.expected_remaining)
# 
#         categories = compute_monthly_categories_from_config(config, date, storage)
#         for category in categories:
#             if category.has_warning:
#                 notify_using_config(config, 'BUDGET: /!\ CATEGORY WARNING: %s (%s / %s)' % (
#                     category.name, category.amount, category.warning_threshold))
# 
# def load_yearly_budgets_from_config(config, date, compute_budget_goals=True, storage=None):
#     if not storage:
#         storage = get_storage_from_config(config)
#     start_date = date.replace(day=1, month=1)
#     end_date = start_date.replace(year=start_date.year+1)
#     if start_date.year <= datetime.date.today().year:
#         end_date = min(datetime.date.today().replace(day=1) + monthdelta(1), end_date)
# 
#     transactions = storage.load_yearly_transactions(date)
#     if config.get('income_delay'):
#         transactions.extend(storage.load_monthly_transactions(end_date))
# 
#     return budgetize_from_config(config, transactions, start_date, end_date, compute_budget_goals)
# 
# def notify_using_config(config, message):
#     print message
#     if config.get('notify_adapter'):
#         adapter = import_module('budgettracker.notify_adapters.' + config['notify_adapter'])
#         adapter.send(config, message)
# 
# def compute_yearly_budget_goals_from_config(config, date, storage=None, debug=False):
#     return compute_budget_goals(
#         load_yearly_budgets_from_config(config, date, False, storage),
#         map(BudgetGoal.from_dict, config.get('budget_goals', [])),
#         debug=debug
#     )
# 
# def compute_monthly_categories_from_config(config, date, storage=None):
#     if not storage:
#         storage = get_storage_from_config(config)
#     categories = map(Category.from_dict, config.get('categories', []))
#     transactions = storage.load_monthly_transactions(date)
#     return compute_categories(transactions, categories)
# 
# def rematch_categories(config, storage=None):
#     if not storage:
#         storage = get_storage_from_config(config)
#     categories = map(Category.from_dict, config.get('categories', []))
#     def iterator(tx):
#         return tx.update(
#             categories=list(set(tx.categories or []) | set(match_categories(categories, tx.label))))
#     storage.iter_all_transactions_for_update(iterator)
# 
# def get_storage_from_config(config):
#     return get_storage(config.get('storage', 'csv'))(config)
# 
# def create_amount_formatter(config):
#     def formatter(amount, show_sign=False):
#         sign = ''
#         if show_sign or amount < 0:
#             sign = '+' if amount >= 0 else '-'
#             amount = abs(amount)
#         return config.get('amount_format', '{sign}${amount:.2f}').format(sign=sign, amount=amount)
#     return formatter
# 
# Path: budgettracker/storage.py
# def get_storage(name):
#     for o in globals().values():
#         if inspect.isclass(o) and issubclass(o, StorageBase) and o is not StorageBase and o.name == name:
#             return o


# Path: budgettracker/cli.py
from .helpers import (load_config, update_local_data, load_yearly_budgets_from_config, notify_using_config,
                      compute_yearly_budget_goals_from_config, compute_monthly_categories_from_config,
                      rematch_categories, get_storage_from_config, create_amount_formatter)
from .storage import get_storage
from getopt import getopt
    from .web import app
import datetime, sys, os, json

# -*- coding: utf-8 -*-


config = load_config()
storage = get_storage_from_config(config)
famount = create_amount_formatter(config)
commands = {}


def command(options='', long_options=None):
    def decorator(func):
        commands[func.__name__] = (func, options, long_options or [])
        return func
    return decorator


@command('', ['month=', 'year=', 'reset'])
def update(filename=None, month=None, year=None, reset=False):
    date = None
    if month or year:
        if not month:
            month = datetime.date.today().month
        if not year:
            year = datetime.date.today().year

        date = datetime.date(int(year), int(month), 1)