#pylint: disable=too-many-public-methods,import-error,too-few-public-methods,missing-docstring,unused-variable
import os
import shutil
import tempfile
import unittest
from gleetex import caching

def write(path, content):
   with open(path, 'w', encoding='utf-8') as f:
       f.write(content)

class test_caching(unittest.TestCase):
   def setUp(self):
       self.pos = {'height' : 8, 'depth' : 2, 'width' : 666}
       self.original_directory = os.getcwd()
       self.tmpdir = tempfile.mkdtemp()
       os.chdir(self.tmpdir)

   def tearDown(self):
       os.chdir(self.original_directory)
       shutil.rmtree(self.tmpdir, ignore_errors=True)

   def test_differently_spaced_formulas_are_the_same(self):
       form1 = r'\tau  \pi'
       form2 = '\tau\\pi'
       self.assertTrue(caching.normalize_formula(form1),
               caching.normalize_formula(form2))

   def test_trailing_and_leading_spaces_and_tabs_are_no_problem(self):
       u = caching.normalize_formula
       form1 = '  hi'
       form2 = 'hi  '
       form3 = '\thi'
       self.assertEqual(u(form1), u(form2))
       self.assertEqual(u(form1), u(form3))

   def test_that_empty_braces_are_ignored(self):
       u = caching.normalize_formula
       form1 = r'\sin{}x'
       form2 = r'\sin x'
       form3 = r'\sin{} x'
       self.assertEqual(u(form1), u(form2))
       self.assertEqual(u(form1), u(form3))
       self.assertEqual(u(form2), u(form3))

   def test_empty_cache_works_fine(self):
       write('foo.png', 'muha')
       c = caching.ImageCache('file.png')
       formula = r"f(x) = \ln(x)"
       c.add_formula(formula, self.pos, 'foo.png')
       self.assertTrue(c.contains(formula, False))

   def test_that_invalid_cach_entries_are_detected(self):
       # entry is invalid if file doesn't exist
       c = caching.ImageCache()
       formula = r"f(x) = \ln(x)"
       self.assertRaises(OSError, c.add_formula, formula, self.pos, 'file.png')

   def test_that_correct_pos_and_path_are_returned_after_writing_the_cache_back(self):
       c = caching.ImageCache()
       formula = r"g(x) = \ln(x)"
       write('file.png', 'dummy')
       c.add_formula(formula, self.pos, 'file.png', displaymath=False)
       c.write()
       c = caching.ImageCache()
       self.assertTrue(c.contains(formula, False))
       data = c.get_data_for(formula, False)
       self.assertEqual(data['pos'], self.pos)
       self.assertEqual(data['path'], 'file.png')


   def test_formulas_are_not_added_twice(self):
       form1 = r'\ln(x) \neq e^x'
       write('spass.png', 'binaryBinary_binary')
       c = caching.ImageCache()
       for i in range(1,10):
           c.add_formula(form1, self.pos, 'spass.png')
       self.assertEqual(len(c), 1)

   def test_that_remove_actually_removes(self):
       form1 = '\\int e^x dy'
       write('happyness.png', 'binaryBinary_binary')
       c = caching.ImageCache()
       c.add_formula(form1, self.pos, 'happyness.png')
       c.remove_formula(form1, False)
       self.assertEqual(len(c), 0)

   def test_removal_of_non_existing_formula_raises_exception(self):
       c = caching.ImageCache()
       self.assertRaises(KeyError, c.remove_formula, 'Haha!', False)

   def test_that_invalid_version_is_detected(self):
       c = caching.ImageCache('gladtex.cache')
       c._ImageCache__set_version('invalid.stuff')
       c.write()
       self.assertRaises(caching.JsonParserException, caching.ImageCache, 'gladtex.cache')

   def test_that_invalid_style_is_detected(self):
       write('foo.png', "dummy")
       c = caching.ImageCache('gladtex.cache')
       c.add_formula('\\tau', self.pos, 'foo.png', False)
       c.add_formula('\\theta', self.pos, 'foo.png', True)
       self.assertRaises(ValueError, c.add_formula, '\\gamma', self.pos, 'foo.png',
               'some stuff')

   def test_that_backslash_in_path_is_replaced_through_slash(self):
       c = caching.ImageCache('gladtex.cache')
       os.mkdir('bilder')
       write(os.path.join('bilder', 'foo.png'), str(0xdeadbeef))
       c.add_formula('\\tau', self.pos, 'bilder\\foo.png', False)
       self.assertTrue('/' in c.get_data_for('\\tau', False)['path'])

   def test_that_absolute_paths_trigger_OSError(self):
       c = caching.ImageCache('gladtex.cache')
       write('foo.png', "dummy")
       fn = os.path.abspath('foo.png')
       self.assertRaises(OSError, c.add_formula, '\\tau', self.pos,
               fn, False)

   def test_that_invalid_caches_are_removed_automatically_if_desired(self):
       file_was_removed = lambda x: self.assertFalse(os.path.exists(x),
               "expected that file %s was removed, but it still exists" % x)
       write('gladtex.cache', 'some non-json rubbish')
       c = caching.ImageCache('gladtex.cache', keep_old_cache=False)
       file_was_removed('gladtex.cache')
       # try the same in a subdirectory
       os.mkdir('foo')
       cache_path = os.path.join('foo', 'gladtex.cache')
       eqn1_path = os.path.join('foo', 'eqn000.png')
       eqn2_path = os.path.join('foo', 'eqn003.png')
       write(cache_path, 'some non-json rubbish')
       write(eqn1_path, 'binary')
       write(eqn2_path, 'more binary')
       c = caching.ImageCache(cache_path, keep_old_cache=False)
       file_was_removed(cache_path)
       file_was_removed(eqn1_path)
       file_was_removed(eqn2_path)

   def test_that_formulas_in_cache_with_no_file_raise_key_error(self):
       c = caching.ImageCache('gladtex.cache', keep_old_cache=False)
       write('foo.png', 'dummy')
       c.add_formula('\\tau', self.pos, 'foo.png')
       c.write()
       os.remove('foo.png')
       c = caching.ImageCache('gladtex.cache', keep_old_cache=False)
       with self.assertRaises(KeyError):
           c.get_data_for('foo.png', 'False')