#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8

'''
  Database manager
  ----------------

  Fetch and store quotes data. The --universe parameter works like the one in
  Intuition configuration.

  :copyright (c) 2014 Xavier Bruhiere.
  :license: Apache 2.0, see LICENSE for more details.
'''


import sys
import argparse
from clint.textui import puts, colored, indent
import pytz
import datetime as dt
import dna.debug
import intuition.utils
import intuition.data.universe as universe
from insights.plugins.database import RethinkdbFinance
from intuition.data.quandl import DataQuandl
import intuition.data.ystockquote as ystockquote


def parse_cli():
    parser = argparse.ArgumentParser(
        description='Intuition-db, quotes database manager')
    parser.add_argument('-V', '--version',
                        action='version',
                        version='%(prog)s v0.0.1 Licence Apache 2.0',
                        help='Print program version')
    parser.add_argument('command', type=str,
                        help='command [dl, sync]')
    parser.add_argument('-v', '--verbose',
                        action='store_true',
                        help='Print logs on stdout')
    parser.add_argument('-u', '--universe',
                        action='store', required=True,
                        help='market universe to evaluate')
    parser.add_argument('-s', '--start',
                        action='store', default='2011-01-01',
                        help='start date for quotes')
    parser.add_argument('-e', '--end',
                        action='store', default=dt.date.today(),
                        help='end date for quotes')
    parser.add_argument('-b', '--backend',
                        action='store', default='rethinkdb',
                        help='database backend to use for storage')
    return parser.parse_args()


def msg(body, indentation=2):
    with indent(indentation, 'info | '):
        puts(colored.blue(body))


def warning(body, indentation=2):
    with indent(indentation, 'warn | '):
        puts(colored.red(body))


def fill_stock_metadata(sid):
    metadata = {}
    try:
        metadata['name'] = ystockquote.get_company_name(sid)
    except Exception, error:
        print(error)
        sys.exit(warning('sometimes it just times out, retry later'))
    metadata['exchange'] = ystockquote.get_stock_exchange(sid)
    if metadata['exchange'].find('Nasdaq') > 0:
        # It returns NasdaqNM
        metadata['exchange'] = 'Nasdaq'
    metadata['type'] = ystockquote.get_type(sid)
    metadata['revenue'] = ystockquote.get_revenue(sid)
    #FIXME Almost never found
    #metadata['index'] = ystockquote.get_indices(sid)
    metadata['sector'] = ystockquote.get_sector(sid)
    metadata['industry'] = ystockquote.get_industry(sid)

    msg('successfully fetched metadata about {}'.format(sid))
    msg(dna.debug.emphasis(metadata))
    return metadata


def store(backend, sid, data, reset=True):
    if not data.isnull().any().any():
        msg('saving {} in database'.format(sid))
        backend.save_quotes(sid, data, {}, reset=reset)
    else:
        warning('{}: empty dataset'.format(sid))


def main():
    msg('- Intuition database manager')
    warning('Currently, only supports cac40 and forex symbols', 4)

    args = parse_cli()

    market = universe.Market()
    market.parse_universe_description(args.universe)
    sids = market.sids

    msg('using {} backend for storage'.format(args.backend))
    db = RethinkdbFinance(db='quotes')

    feed = DataQuandl()

    #TODO Fetch more informations
    if args.command == 'dl':
        start = intuition.utils.normalize_date_format(args.start)
        if isinstance(args.end, str):
            end = intuition.utils.normalize_date_format(args.end)
        else:
            end = args.end
        reset = True

    elif args.command == 'sync':
        # TODO Per quote sync
        younger_date = dt.datetime(2020, 1, 1, tzinfo=pytz.utc)
        for sid in sids:
            last_entry = db.last_chrono_entry(sid)
            if last_entry['date'] < younger_date:
                younger_date = last_entry['date']

        start = younger_date + dt.timedelta(1)
        end = dt.date.today()
        reset = False

    else:
        raise ValueError('unknown command: {}'.format(args.command))

    # FIXME Quandl will fetch about 10 sids max
    msg('downloading {} data ({} -> {})'.format(sids, start, end), 4)
    data = feed.fetch(
        sids, start=start, end=end, returns='pandas')
    msg('done')

    for sid in data:
        try:
            store(backend=db, sid=sid, data=data[sid], reset=reset)
        except Exception as error:
            print(error)
            continue
    msg('done')


if __name__ == '__main__':
    sys.exit(main())
