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

from __future__ import print_function
from __future__ import absolute_import
import os
import sys
import time
import tempfile
import warnings

import tables
from tables import Group, Leaf, Table, Array
from tables import StringCol, IntCol, Int16Col, FloatCol, Float32Col

from tables.tests import common
from tables.tests.common import unittest
from tables.tests.common import PyTablesTestCase as TestCase
from six.moves import range


# Test Record class
class Record(tables.IsDescription):
    var1 = StringCol(itemsize=4)  # 4-character String
    var2 = IntCol()              # integer
    var3 = Int16Col()            # short integer
    var4 = FloatCol()            # double (double-precision)
    var5 = Float32Col()          # float  (single-precision)


class TreeTestCase(common.TempFileMixin, TestCase):
    open_mode = "w"
    title = "This is the table title"
    expectedrows = 10
    appendrows = 5

    def setUp(self):
        super(TreeTestCase, self).setUp()

        # Create an instance of HDF5 Table
        self.populateFile()
        self.h5file.close()

    def populateFile(self):
        group = self.h5file.root
        maxshort = 1 << 15
        # maxint   = 2147483647   # (2 ** 31 - 1)
        for j in range(3):
            # Create a table
            table = self.h5file.create_table(group, 'table'+str(j), Record,
                                             title=self.title,
                                             filters=None,
                                             expectedrows=self.expectedrows)
            # Get the record object associated with the new table
            d = table.row
            # Fill the table
            for i in range(self.expectedrows):
                d['var1'] = '%04d' % (self.expectedrows - i)
                d['var2'] = i
                d['var3'] = i % maxshort
                d['var4'] = float(i)
                d['var5'] = float(i)
                d.append()      # This injects the Record values
            # Flush the buffer for this table
            table.flush()

            # Create a couple of arrays in each group
            var1List = [x['var1'] for x in table.iterrows()]
            var4List = [x['var4'] for x in table.iterrows()]

            self.h5file.create_array(group, 'var1', var1List, "1")
            self.h5file.create_array(group, 'var4', var4List, "4")

            # Create a new group (descendant of group)
            group2 = self.h5file.create_group(group, 'group'+str(j))
            # Iterate over this new group (group2)
            group = group2

    def test00_getNode(self):
        """Checking the File.get_node() with string node names"""

        if common.verbose:
            print('\n', '-=' * 30)
            print("Running %s.test00_getNode..." % self.__class__.__name__)

        self.h5file = tables.open_file(self.h5fname, "r")
        nodelist = ['/', '/table0', '/group0/var1', '/group0/group1/var4']
        nodenames = []
        for node in nodelist:
            object = self.h5file.get_node(node)
            nodenames.append(object._v_pathname)

        self.assertEqual(nodenames, nodelist)
        if common.verbose:
            print("get_node(pathname) test passed")
        nodegroups = [
            '/', '/group0', '/group0/group1', '/group0/group1/group2']
        nodenames = ['var1', 'var4']
        nodepaths = []
        for group in nodegroups:
            for name in nodenames:
                try:
                    object = self.h5file.get_node(group, name)
                except LookupError:
                    pass
                else:
                    nodepaths.append(object._v_pathname)

        self.assertEqual(nodepaths,
                         ['/var1', '/var4',
                          '/group0/var1', '/group0/var4',
                          '/group0/group1/var1', '/group0/group1/var4'])

        if common.verbose:
            print("get_node(groupname, name) test passed")
        nodelist = ['/', '/group0', '/group0/group1', '/group0/group1/group2',
                    '/table0']
        nodenames = []
        groupobjects = []
        # warnings.filterwarnings("error", category=UserWarning)
        for node in nodelist:
            try:
                object = self.h5file.get_node(node, classname='Group')
            except LookupError:
                if common.verbose:
                    (type, value, traceback) = sys.exc_info()
                    print("\nGreat!, the next LookupError was catched!")
                    print(value)
            else:
                nodenames.append(object._v_pathname)
                groupobjects.append(object)

        self.assertEqual(nodenames,
                         ['/', '/group0', '/group0/group1',
                          '/group0/group1/group2'])
        if common.verbose:
            print("get_node(groupname, classname='Group') test passed")

        # Reset the warning
        # warnings.filterwarnings("default", category=UserWarning)

        nodenames = ['var1', 'var4']
        nodearrays = []
        for group in groupobjects:
            for name in nodenames:
                try:
                    object = self.h5file.get_node(group, name, 'Array')
                except:
                    pass
                else:
                    nodearrays.append(object._v_pathname)

        self.assertEqual(nodearrays,
                         ['/var1', '/var4',
                          '/group0/var1', '/group0/var4',
                          '/group0/group1/var1', '/group0/group1/var4'])
        if common.verbose:
            print("get_node(groupobject, name, classname='Array') test passed")

    def test01_getNodeClass(self):
        """Checking the File.get_node() with instances"""

        if common.verbose:
            print('\n', '-=' * 30)
            print("Running %s.test01_getNodeClass..." %
                  self.__class__.__name__)

        self.h5file = tables.open_file(self.h5fname, "r")

        # This tree ways of get_node usage should return a table instance
        table = self.h5file.get_node("/group0/table1")
        self.assertTrue(isinstance(table, Table))