# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved

# Python
from __future__ import absolute_import
import os
import json

# Django
from django.utils.timezone import now
from dateutil.relativedelta import relativedelta

# AWX
from awx.fact.models.fact import * # noqa
from awx.fact.tests.base import BaseFactTest, FactScanBuilder, TEST_FACT_PACKAGES

__all__ = ['FactHostTest', 'FactTest', 'FactGetHostVersionTest', 'FactGetHostTimelineTest']

# damn you python 2.6
def timedelta_total_seconds(timedelta):
    return (
        timedelta.microseconds + 0.0 +
        (timedelta.seconds + timedelta.days * 24 * 3600) * 10 ** 6) / 10 ** 6


class FactHostTest(BaseFactTest):
    def test_create_host(self):
        host = FactHost(hostname='hosty', inventory_id=1)
        host.save()

        host = FactHost.objects.get(hostname='hosty', inventory_id=1)
        self.assertIsNotNone(host, "Host added but not found")
        self.assertEqual('hosty', host.hostname, "Gotten record hostname does not match expected hostname")
        self.assertEqual(1, host.inventory_id, "Gotten record inventory_id does not match expected inventory_id")

    # Ensure an error is raised for .get() that doesn't match a record.
    def test_get_host_id_no_result(self):
        host = FactHost(hostname='hosty', inventory_id=1)
        host.save()

        self.assertRaises(FactHost.DoesNotExist, FactHost.objects.get, hostname='doesnotexist', inventory_id=1)

class FactTest(BaseFactTest):
    def setUp(self):
        super(FactTest, self).setUp()

    def test_add_fact(self):
        timestamp = now().replace(microsecond=0)
        host = FactHost(hostname="hosty", inventory_id=1).save()
        (f_obj, v_obj) = Fact.add_fact(host=host, timestamp=timestamp, module='packages', fact=TEST_FACT_PACKAGES)
        f = Fact.objects.get(id=f_obj.id)
        v = FactVersion.objects.get(id=v_obj.id)

        self.assertEqual(f.id, f_obj.id)
        self.assertEqual(f.module, 'packages')
        self.assertEqual(f.fact, TEST_FACT_PACKAGES)
        self.assertEqual(f.timestamp, timestamp)

        # host relationship created
        self.assertEqual(f.host.id, host.id)

        # version created and related
        self.assertEqual(v.id, v_obj.id)
        self.assertEqual(v.timestamp, timestamp)
        self.assertEqual(v.host.id, host.id)
        self.assertEqual(v.fact.id, f_obj.id)
        self.assertEqual(v.fact.module, 'packages')

    # Note: Take the failure of this with a grain of salt.
    # The test almost entirely depends on the specs of the system running on.
    def test_add_fact_performance_4mb_file(self):
        timestamp = now().replace(microsecond=0)
        host = FactHost(hostname="hosty", inventory_id=1).save()

        from awx.fact import tests
        with open('%s/data/file_scan.json' % os.path.dirname(os.path.realpath(tests.__file__))) as f:
            data = json.load(f)

            t1 = now()
            (f_obj, v_obj) = Fact.add_fact(host=host, timestamp=timestamp, module='packages', fact=data)
            t2 = now()
            diff = timedelta_total_seconds(t2 - t1)
            print("add_fact save time: %s (s)" % diff)
            # Note: 20 is realllly high. This should complete in < 2 seconds
            self.assertLessEqual(diff, 20)

            Fact.objects.get(id=f_obj.id)
            FactVersion.objects.get(id=v_obj.id)

class FactGetHostVersionTest(BaseFactTest):
    def setUp(self):
        super(FactGetHostVersionTest, self).setUp()
        self.builder = FactScanBuilder()
        self.builder.add_fact('packages', TEST_FACT_PACKAGES)
        self.builder.build(scan_count=2, host_count=1)

    def test_get_host_version_exact_timestamp(self):
        fact_known = self.builder.get_scan(0, 'packages')[0]
        fact = Fact.get_host_version(hostname=self.builder.get_hostname(0), inventory_id=self.builder.get_inventory_id(), timestamp=self.builder.get_timestamp(0), module='packages')
        self.assertIsNotNone(fact)
        self.assertEqual(fact_known, fact)

    def test_get_host_version_lte_timestamp(self):
        timestamp = self.builder.get_timestamp(0) + relativedelta(days=1)
        fact_known = self.builder.get_scan(0, 'packages')[0]
        fact = Fact.get_host_version(hostname=self.builder.get_hostname(0), inventory_id=self.builder.get_inventory_id(), timestamp=timestamp, module='packages')
        self.assertIsNotNone(fact)
        self.assertEqual(fact_known, fact)

    def test_get_host_version_none(self):
        timestamp = self.builder.get_timestamp(0) - relativedelta(years=20)
        fact = Fact.get_host_version(hostname=self.builder.get_hostname(0), inventory_id=self.builder.get_inventory_id(), timestamp=timestamp, module='packages')
        self.assertIsNone(fact)

class FactGetHostTimelineTest(BaseFactTest):
    def setUp(self):
        super(FactGetHostTimelineTest, self).setUp()
        self.builder = FactScanBuilder()
        self.builder.add_fact('packages', TEST_FACT_PACKAGES)
        self.builder.build(scan_count=20, host_count=1)

    def test_get_host_timeline_ok(self):
        timestamps = Fact.get_host_timeline(hostname=self.builder.get_hostname(0), inventory_id=self.builder.get_inventory_id(), module='packages')
        self.assertIsNotNone(timestamps)
        self.assertEqual(len(timestamps), self.builder.get_scan_count())
        for i in range(0, self.builder.get_scan_count()):
            self.assertEqual(timestamps[i], self.builder.get_timestamp(i))
