import pickle
import hashlib
import datetime
import logging
import dateutil.parser
from django.db import models
from django.db.models import Q
from django.db.models import Max, Min
from django_pgjson.fields import JsonField
from core.utilities import check_domain_valid, get_base_domain
from pivoteer.records import RecordType, RecordSource
from core.lookups import geolocate_ip

LOGGER = logging.getLogger(__name__)

class IndicatorManager(models.Manager):

    def host_records(self, indicator):
        record_type = RecordType.HR

        records = self.get_queryset().filter(Q(record_type=record_type.name),
                                             Q(indicator=indicator))
        return records

    def recent_cert(self, indicator):
        """Retrieve the most recent censys.io certificate result for the provided indicator
        # Updated by LNguyen
        # Date: 05May2017
            Args:
                indicator (str): The indicator to search for
            
            Returns (IndicatorRecord): The IndicatorRecord for the most recently saved
                result for the provided indicator or an empty query set if no record was found.
        """
        
        # TODO: Why are we returning empty query sets hiversus None when there are no results?
        
        record_type = RecordType.CE
        time_frame = datetime.datetime.utcnow() + datetime.timedelta(hours=-24)

        records = self.get_queryset().filter(Q(record_type=record_type.name),
                                             Q(info_date__gte=time_frame),
                                             Q(indicator=indicator)).values('info', 'info_date')

        # records = self.get_queryset().filter(Q(record_type=record_type.name),
        #                                      Q(info_date__gte=time_frame),
        #                                      Q(info__at_indicator__exact=indicator)).values('info', 'info_date')
        if records:
            return records.latest('info_date')
        LOGGER.info("Failed to retrieve certificate data for indicator %s" % indicator)
        return records

    def recent_tc(self, indicator):
        """Retrieve the most recent ThreatCrowd record for the provided indicator
        # Updated by LNguyen
        # Date: 05May2017

            Args:
                indicator (str): The indicator to search for

            Returns (IndicatorRecord): The indicator record for the most recently saved
                result for the provided indicator.
        """
        record_type = RecordType.TR
        time_frame = datetime.datetime.utcnow() + datetime.timedelta(hours=-24)

        records = self.get_queryset().filter(Q(record_type=record_type.name),
                                             Q(info_date__gte=time_frame),
                                             Q(indicator=indicator)).values('info', 'info_date')
        # records = self.get_queryset().filter(Q(record_type=record_type.name),
        #                                      Q(info_date__gte=time_frame),
        #                                      Q(info__at_domain__exact=indicator) |
        #                                      Q(info__at_ip__exact=indicator)).values('info', 'info_date')


        if records:
            return records.latest('info_date')
        LOGGER.info("Failed to retrieve ThreatCrowd data for indicator %s" % indicator)
        return records

    def recent_hosts(self, indicator):
        # Updated by LNguyen
        # Date: 1Aug2017
        # Description: Update query to return only recent DNS data and exclude PDNS and Passive Total Data
        record_type = RecordType.HR
        time_frame = datetime.datetime.utcnow() + datetime.timedelta(hours=-24)

        records = self.get_queryset().filter(~Q(info_source=RecordSource.PDS.name),
                                             ~Q(info_source=RecordSource.PTO.name),
                                             Q(record_type=record_type.name),
                                             Q(info_date__gte=time_frame),
                                             Q(indicator=indicator))

        # records = self.get_queryset().filter(Q(record_type=record_type.name),
        #                                      Q(info_date__gte=time_frame),
        #                                      Q(info__at_domain__endswith=indicator) |
        #                                      Q(info__at_ip__endswith=indicator))


        return records

    def dns_historical_hosts(self, indicator, request):
        # Updated by LNguyen
        # Date: 1Aug2017
        # Description: Query to retrieve Historical DNS dataset
        record_type = RecordType.HR
        time_frame = datetime.datetime.utcnow() + datetime.timedelta(hours=-24)
        time_start = datetime.datetime.utcnow() - datetime.timedelta(days=366)


        records = self.get_queryset().filter(Q(info_source=RecordSource.DNS.name),
                                                 Q(record_type=record_type.name),
                                                 Q(info_date__lt=time_frame),
                                                 Q(indicator=indicator)).values('info', 'info_date', 'info_source')

        return records

    def historical_hosts(self, indicator, request):
        # Updated by LNguyen
        # Date: 1Aug2017
        # Description: Query to retrieve other Historical dataset (with exception of PDNS and DNS data because they're handled in separate queries) 
        #         This query also includes Passive Total Data in the dataset. 
        record_type = RecordType.HR
        time_frame = datetime.datetime.utcnow() + datetime.timedelta(hours=-24)
        time_start = datetime.datetime.utcnow() - datetime.timedelta(days=366)

        if request.user.is_staff: