from __future__ import absolute_import
from pychron.core.test_helpers import get_data_dir as mget_data_dir, dvc_db_factory

__author__ = "ross"

import os
import unittest

from pychron.core.ui import set_qt

set_qt()

from pychron.entry.loaders.irradiation_loader import XLSIrradiationLoader

TEST_PARSE_XLS = False
DEBUGGING = False

# automatically disable debugging if running on a travis ci linux box.
import sys

if sys.platform != "darwin":
    DEBUGGING = False

DBNAME = "loader.db"

if DEBUGGING:
    from pychron.core.helpers.logger_setup import logging_setup

    logging_setup("irrad_loader")


def get_data_dir():
    op = "pychron/entry/tests/data"
    return mget_data_dir(op)
    # if not os.path.isdir(op):
    #     op = os.path.join('.', 'data')
    # return op


def db_factory():
    path = os.path.join(get_data_dir(), DBNAME)
    db = dvc_db_factory(path)
    # from pychron.database.adapters.isotope_adapter import IsotopeAdapter
    # from pychron.database.orms.isotope.util import Base
    #
    # db = IsotopeAdapter()
    # db.verbose_retrieve_query = True
    # db.trait_set(kind='sqlite', path=os.path.join(get_data_dir(), DBNAME))
    # db.connect()
    #
    # if os.path.isfile(db.path):
    #     os.remove(db.path)
    #
    # metadata = Base.metadata
    # db.create_all(metadata)
    # with db.session_ctx() as sess:
    # metadata.create_all(sess.bind)

    return db


class XLSIrradiationLoaderLoadTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.loader = XLSIrradiationLoader()
        p = os.path.join(get_data_dir(), "irradiation_import.xls")
        cls.input_path = p

    def setUp(self):
        self.loader.open(self.input_path)
        # rebuild the local db
        self.loader.db = db_factory()

    # @unittest.skipIf(DEBUGGING, 'Debugging tests')
    # def test_add_irradiation_dry(self):
    #     self.loader.db.add_irradiation('NM-1000', dry=True)
    #     obj = self.loader.db.get_irradiation('NM-1000')
    #     self.assertIsNone(obj)

    @unittest.skipIf(DEBUGGING, "Debugging tests")
    def test_add_irradiation(self):
        self.loader.db.add_irradiation("NM-1000")
        obj = self.loader.db.get_irradiation("NM-1000")
        self.assertEqual(obj.name, "NM-1000")

    # @unittest.skipIf(DEBUGGING, 'Debugging tests')
    # def test_add_level_dry(self):
    #     self.loader.add_irradiation('NM-1000')
    #     self.loader.add_irradiation_level('NM-1000', 'A', '8-Hole', 1, dry=True)
    #     obj = self.loader.db.get_irradiation_level('NM-1000', 'A')
    #     self.assertIsNone(obj)

    @unittest.skipIf(DEBUGGING, "Debugging tests")
    def test_add_level(self):
        self.loader.db.add_irradiation("NM-1000")
        self.loader.db.add_irradiation_level("A", "NM-1000", "8-Hole", "TRIGA", 1)

        obj = self.loader.db.get_irradiation_level("NM-1000", "A")
        self.assertTupleEqual((obj.irradiation.name, obj.name), ("NM-1000", "A"))

    def _default_pdict(self, **kw):
        pdict = {
            "irradiation": "NM-1000",
            "level": "A",
            "position": 1,
            "material": "sanidine",
            "project": "Test",
            "sample": "FC-2",
            "is_monitor": True,
            "weight": 100,
            "identifier": None,
            "note": "this is a note",
        }
        pdict.update(**kw)
        return pdict

    # @unittest.skipIf(DEBUGGING, 'Debugging tests')
    # def test_add_position_dry(self):
    #     self.loader.add_irradiation('NM-1000')
    #     self.loader.add_irradiation_level('NM-1000', 'A', '8-Hole', 1, add_positions=False)
    #     pdict = self._default_pdict()
    #
    #     self.loader.add_position(pdict, dry=True)
    #
    #     obj = self.loader.db.get_irradiation_position('NM-1000', 'A', 1)
    #     self.assertIsNone(obj)

    @unittest.skipIf(DEBUGGING, "Debugging tests")
    def test_add_position(self):
        self.loader.db.add_irradiation("NM-1000")
        self.loader.db.add_irradiation_level("A", "NM-1000", "8-Hole", "TRIGA", 1)

        self.loader.db.add_irradiation_position("NM-1000", "A", 1, identifier="1000")
        obj = self.loader.db.get_irradiation_position("NM-1000", "A", 1)
        self.assertTupleEqual(
            (obj.position, obj.level.name, obj.level.irradiation.name, obj.identifier),
            (1, "A", "NM-1000", "1000"),
        )

    @unittest.skipIf(DEBUGGING, "Debugging tests")
    def test_generate_labnumber(self):
        self.loader.irradiation_offset = 1000
        gen = self.loader.identifier_generator()

        self.assertEqual((next(gen), next(gen)), (1000, 1001))

    @unittest.skipIf(DEBUGGING, "Debugging tests")
    def test_generate_labnumber2(self):
        # add a placeholder labnumber
        self.loader.db.add_irradiation("NM-1000")
        self.loader.db.add_irradiation_level("A", "NM-1000", "8-Hole", "TRIGA", 1)
        self.loader.db.add_irradiation_position("NM-1000", "A", 1, identifier="2500")

        self.loader.irradiation_offset = 100
        gen = self.loader.identifier_generator()

        self.assertEqual((next(gen), next(gen)), (2600, 2601))

        # @unittest.skipIf(DEBUGGING, 'Debugging tests')
        # def test_generate_offsets2(self):
        #     # add a placeholder labnumber
        #     self.loader.db.add_labnumber(1000, 'FC-2')
        #
        #     # fool loader into thinking 2 irradiations and 8 level were added (4 to each irradiation)
        #     self.loader._added_irradiations = [0]
        #     self.loader._added_levels = [0, 0, 0, 0]
        #
        #     gen = self.loader.identifier_generator()
        #     self.assertEqual(tuple([gen.next() for i in range(4)]), (2030, 2031, 2032, 2033))
        #
        #     self.loader._added_irradiations = [0, 1]
        #     self.loader._added_levels = [1]
        #     gen = self.loader.identifier_generator()
        #     self.assertEqual(tuple([gen.next() for i in range(4)]), (3000, 3001, 3002, 3003))

        # @unittest.skipIf(DEBUGGING, 'Debugging tests')
        # def test_add_samples(self):
        #     self.loader.autogenerate_labnumber = True
        #     self.loader.add_irradiation('NM-1000')
        #     self.loader.add_irradiation_level('NM-1000', 'A', '8-Hole', 1, add_positions=False)
        #     gen = self.loader.identifier_generator()
        #     for i in range(3):
        #         pdict = self._default_pdict(identifier=gen.next())
        #         self.loader.add_position(pdict)
        #
        #     with self.loader.db.session_ctx():
        #         ps = self.loader.db.get_projects()
        #         self.assertEqual(len(ps), 1)
        #
        #         ms = self.loader.db.get_materials()
        #         self.assertEqual(len(ms), 1)
        #
        #         ss = self.loader.db.get_samples()
        #         self.assertEqual(len(ss), 1)


class XLSIrradiationLoaderParseTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.loader = XLSIrradiationLoader()
        p = os.path.join(get_data_dir(), "irradiation_import.xls")
        cls.input_path = p

    def tearDown(self):
        ip = os.path.join(get_data_dir(), "template.xls")
        if os.path.isfile(ip):
            os.remove(ip)

    def setUp(self):
        self.loader.open(self.input_path)

    def test_make_template(self):
        ip = os.path.join(get_data_dir(), "template.xls")
        self.loader.make_template(ip)
        self.assertTrue(os.path.isfile(ip))

    def test_irradiation1(self):
        p = get_data_dir()
        p = os.path.join(p, DBNAME)

        self.assertTrue(os.path.isfile(p))

    def test_iteration1(self):
        irrads = self.loader.iterate_irradiations()
        irrads = list(irrads)
        self.assertEqual(len(irrads), 2)
        self.assertEqual(len(list(irrads[0])), 5)
        self.assertEqual(len(list(irrads[1])), 4)

    def test_iteration2(self):
        irrads = self.loader.iterate_irradiations()
        irrads = list(irrads)

        airrad = irrads[0]
        birrad = irrads[1]
        aheader = next(airrad)
        bheader = next(birrad)

        self.assertEqual("NM-1000", aheader[0].value)
        self.assertEqual("NM-1001", bheader[0].value)

    def test_iteration3(self):
        p = os.path.join(get_data_dir(), "iterate_irradiations.xls")
        self.loader.open(p)

        irrads = self.loader.iterate_irradiations()
        irrads = list(irrads)
        self.assertListEqual(