# -*- coding: utf-8 -*-
import os
import shutil

import pytest

from piecash import Transaction, Commodity, open_book, create_book, Account
from piecash._common import GnucashException
from piecash.core.session import Version, gnclock
from piecash.kvp import Slot
from test_helper import file_template, file_for_test


@pytest.fixture
def session(request):
    s = create_book()
    return s.session


@pytest.fixture
def session_readonly(request):
    shutil.copyfile(file_template, file_for_test)

    # default session is readonly
    s = open_book(file_for_test)

    @request.addfinalizer
    def close_s():
        s.close()
        os.remove(file_for_test)

    return s


@pytest.fixture
def book_readonly_lock(request):
    shutil.copyfile(file_template, file_for_test)

    # default session is readonly
    book = open_book(file_for_test)

    @request.addfinalizer
    def close_s():
        book.close()
        os.remove(file_for_test)

    return book


class TestModelCore_EmptyBook(object):
    def test_accounts(self, session):
        # two accounts in an empty gnucash file
        account_names = session.query(Account.name).all()

        assert set(account_names) == {(u'Template Root',),
                                      (u'Root Account',),
                                      }

    def test_transactions(self, session):
        # no transactions in an empty gnucash file
        transactions = session.query(Transaction).all()
        assert transactions == []

    def test_commodities(self, session):
        # no commodities in an empty gnucash file
        commodities = session.query(Commodity.mnemonic).all()
        assert commodities == [("EUR",)]

    def test_slots(self, session):
        # no slots in an empty gnucash file but the default_currency
        slots = session.query(Slot._name).all()
        assert slots == [('default-currency',)]

    def test_versions(self, session):
        # confirm versions of tables
        versions = session.query(Version.table_name,
                                 Version.table_version).all()
        assert set(versions) == {(u'Gnucash', 2060400), (u'Gnucash-Resave', 19920),
                                 (u'accounts', 1), (u'books', 1),
                                 (u'budgets', 1), (u'budget_amounts', 1), ('jobs', 1), (u'orders', 1),
                                 (u'taxtables', 2), (u'taxtable_entries', 3), (u'vendors', 1), (u'recurrences', 2),
                                 (u'slots', 3), (u'transactions', 3), (u'splits', 4), (u'lots', 2), (u'entries', 3),
                                 (u'billterms', 2), (u'invoices', 3), (u'commodities', 1), (u'schedxactions', 1),
                                 (u'prices', 2), (u'customers', 2), (u'employees', 2),
                                 }

    def test_readonly_true(self, session_readonly):
        # control exception when adding object to readonly gnucash db
        v = Version(table_name="sample", table_version="other sample")
        sa_session_readonly = session_readonly.session
        sa_session_readonly.add(v)
        with pytest.raises(GnucashException):
            sa_session_readonly.commit()

        # control exception when deleting object to readonly gnucash db
        sa_session_readonly.delete(session_readonly.query(Account).first())
        with pytest.raises(GnucashException):
            sa_session_readonly.commit()

        # control exception when modifying object to readonly gnucash db
        sa_session_readonly.query(Account).first().name = "foo"
        with pytest.raises(GnucashException):
            sa_session_readonly.commit()

    def test_readonly_false(self, session):
        v = Version(table_name="fo", table_version="ok")
        session.add(v)
        assert session.flush() is None

    def test_lock(self, book_readonly_lock):
        # test that lock is not taken in readonly session
        locks = list(book_readonly_lock.session.execute(gnclock.select()))
        assert len(locks) == 0
