import unittest

from app import app
from util.imagetree import ImageTree
from initdb import setup_database_for_testing, finished_database_for_testing
from data import model

NAMESPACE = 'devtable'
SIMPLE_REPO = 'simple'
COMPLEX_REPO = 'complex'

class TestImageTree(unittest.TestCase):
  def setUp(self):
    setup_database_for_testing(self)
    self.app = app.test_client()
    self.ctx = app.test_request_context()
    self.ctx.__enter__()

  def tearDown(self):
    finished_database_for_testing(self)
    self.ctx.__exit__(True, None, None)

  def _get_base_image(self, all_images):
    for image in all_images:
      if image.ancestors == '/':
        return image

    return None

  def test_longest_path_simple_repo(self):
    all_images = list(model.image.get_repository_images(NAMESPACE, SIMPLE_REPO))
    all_tags = list(model.tag.list_repository_tags(NAMESPACE, SIMPLE_REPO))
    tree = ImageTree(all_images, all_tags)

    base_image = self._get_base_image(all_images)
    tag_image = all_tags[0].image

    def checker(index, image):
      return True

    ancestors = tag_image.ancestors.split('/')[2:-1] # Skip the first image.
    result = tree.find_longest_path(base_image.id, checker)
    self.assertEquals(3, len(result))
    for index in range(0, 2):
      self.assertEquals(int(ancestors[index]), result[index].id)

    self.assertEquals('latest', tree.tag_containing_image(result[-1]))

  def test_longest_path_complex_repo(self):
    all_images = list(model.image.get_repository_images(NAMESPACE, COMPLEX_REPO))
    all_tags = list(model.tag.list_repository_tags(NAMESPACE, COMPLEX_REPO))
    tree = ImageTree(all_images, all_tags)

    base_image = self._get_base_image(all_images)

    def checker(index, image):
      return True

    result = tree.find_longest_path(base_image.id, checker)
    self.assertEquals(4, len(result))
    self.assertEquals('prod', tree.tag_containing_image(result[-1]))

  def test_filtering(self):
    all_images = list(model.image.get_repository_images(NAMESPACE, COMPLEX_REPO))
    all_tags = list(model.tag.list_repository_tags(NAMESPACE, COMPLEX_REPO))
    tree = ImageTree(all_images, all_tags, base_filter=1245)

    base_image = self._get_base_image(all_images)

    def checker(index, image):
      return True

    result = tree.find_longest_path(base_image.id, checker)
    self.assertEquals(0, len(result))

  def test_find_tag_parent_image(self):
    all_images = list(model.image.get_repository_images(NAMESPACE, COMPLEX_REPO))
    all_tags = list(model.tag.list_repository_tags(NAMESPACE, COMPLEX_REPO))
    tree = ImageTree(all_images, all_tags)

    base_image = self._get_base_image(all_images)

    def checker(index, image):
      return True

    result = tree.find_longest_path(base_image.id, checker)
    self.assertEquals(4, len(result))

    # Only use the first two images. They don't have tags, but the method should
    # still return the tag that contains them.
    self.assertEquals('staging', tree.tag_containing_image(result[0]))


  def test_longest_path_simple_repo_direct_lookup(self):
    repository = model.repository.get_repository(NAMESPACE, SIMPLE_REPO)
    all_images = list(model.image.get_repository_images(NAMESPACE, SIMPLE_REPO))
    all_tags = list(model.tag.list_repository_tags(NAMESPACE, SIMPLE_REPO))

    base_image = self._get_base_image(all_images)
    tag_image = all_tags[0].image

    def checker(index, image):
      return True

    filtered_images = model.image.get_repository_images_without_placements(repository,
                                                                     with_ancestor=base_image)
    self.assertEquals(set([f.id for f in filtered_images]), set([a.id for a in all_images]))

    tree = ImageTree(filtered_images, all_tags)

    ancestors = tag_image.ancestors.split('/')[2:-1] # Skip the first image.
    result = tree.find_longest_path(base_image.id, checker)
    self.assertEquals(3, len(result))
    self.assertEquals('latest', tree.tag_containing_image(result[-1]))

if __name__ == '__main__':
  unittest.main()