# coding=utf-8
from __future__ import unicode_literals

import yahoo_finance

from .commodity import GncCommodityError
from .._common import GnucashException


def create_stock_accounts(cdty, broker_account, income_account=None, income_account_types="D/CL/I"):
    """Create the multiple accounts used to track a single stock, ie:

    - broker_account/stock.mnemonic

    and the following accounts depending on the income_account_types argument

    - D = Income/Dividend Income/stock.mnemonic
    - CL = Income/Cap Gain (Long)/stock.mnemonic
    - CS = Income/Cap Gain (Short)/stock.mnemonic
    - I = Income/Interest Income/stock.mnemonic

    Args:
        broker_account (:class:`piecash.core.account.Account`): the broker account where the account holding
        the stock is to be created
        income_account (:class:`piecash.core.account.Account`): the income account where the accounts holding
        the income related to the stock are to be created
        income_account_types (str): "/" separated codes to drive the creation of income accounts

    Returns:
        :class:`piecash.core.account.Account`: a tuple with the account under the broker_account where the stock is held
        and the list of income accounts.
    """
    if cdty.namespace == "CURRENCY":
        raise GnucashException("{} is a currency ! You can't create stock_accounts for currencies".format(cdty))

    from .account import Account

    symbol = cdty.mnemonic
    try:
        acc = broker_account.children(name=symbol)
    except KeyError:
        acc = Account(symbol, "STOCK", cdty, broker_account)

    inc_accounts = []
    if income_account:
        cur = cdty.base_currency

        for inc_acc in income_account_types.split("/"):
            sub_account_name = {
                "D": "Dividend Income",
                "CL": "Cap Gain (Long)",
                "CS": "Cap Gain (Short)",
                "I": "Interest Income",
            }[inc_acc]
            try:
                sub_acc = income_account.children(name=sub_account_name)
            except KeyError:
                sub_acc = Account(sub_account_name, "INCOME", cur.base_currency, income_account)
            try:
                cdty_acc = sub_acc.children(name=symbol)
            except KeyError:
                cdty_acc = Account(symbol, "INCOME", cur, sub_acc)
            inc_accounts.append(cdty_acc)

    return acc, inc_accounts


def create_currency_from_ISO(isocode):
    """
    Factory function to create a new currency from its ISO code

    Args:
        isocode (str): the ISO code of the currency (e.g. EUR for the euro)

    Returns:
        :class:`Commodity`: the currency as a commodity object
    """
    from .commodity import Commodity

    # if self.get_session().query(Commodity).filter_by(isocode=isocode).first():
    #     raise GncCommodityError("Currency '{}' already exists".format(isocode))

    from .currency_ISO import ISO_currencies

    cur = ISO_currencies.get(isocode)

    if cur is None:
        raise ValueError("Could not find the ISO code '{}' in the ISO table".format(isocode))

    # create the currency
    cdty = Commodity(mnemonic=cur.mnemonic,
                     fullname=cur.currency,
                     fraction=10 ** int(cur.fraction),
                     cusip=cur.cusip,
                     namespace="CURRENCY",
                     quote_flag=1,
                     )

    # self.gnc_session.add(cdty)
    return cdty


def create_stock_from_symbol(symbol, book=None):
    """
    Factory function to create a new stock from its symbol. The ISO code of the quoted currency of the stock is
    stored in the slot "quoted_currency".

    Args:
        symbol (str): the symbol for the stock (e.g. YHOO for the Yahoo! stock)

    Returns:
        :class:`Commodity`: the stock as a commodity object

    .. note::
       The information is gathered from the yahoo-finance package
       The default currency in which the quote is traded is stored in a slot 'quoted_currency'

    .. todo::
       use 'select * from yahoo.finance.sectors' and 'select * from yahoo.finance.industry where id ="sector_id"'
       to retrieve name of stocks and allow therefore the creation of a stock by giving its "stock name" (or part of it).
       This could also be used to retrieve all symbols related to the same company
    """
    from .commodity import Commodity

    share = yahoo_finance.Share(symbol).data_set
    currency = share["Currency"]
    if not currency:
        raise GncCommodityError("Can't find information on symbol '{}'".format(symbol))

    stock = Commodity(mnemonic=symbol,
                      fullname=share["Name"],
                      fraction=10000,
                      namespace=share["StockExchange"].upper(),
                      quote_flag=1,
                      )
    stock["quoted_currency"] = share["Currency"]

    if book:
        book.session.add(stock)

    return stock


def single_transaction(post_date,
                       enter_date,
                       description,
                       value,
                       from_account,
                       to_account):
    from . import Transaction, Split
    # currency is derived from "from_account" (as in GUI)
    currency = from_account.commodity
    # currency of other destination account should be identical (as only one value given)
    assert currency == to_account.commodity, "Commodities of accounts should be the same"
    tx = Transaction(
        currency=currency,
        post_date=post_date,
        enter_date=enter_date,
        description=description,
        splits=[
            Split(account=from_account, value=-value),
            Split(account=to_account, value=value),
        ])
    return tx
