from __future__ import print_function
from builtins import map
from builtins import range
import sys
import os
from flask_testing import TestCase
from flask import request
from flask import url_for, Flask
import unittest
import requests
from requests.exceptions import ReadTimeout
import time
from object_service import app
import json
import httpretty
import timeout_decorator
import mock
import pytest

class TestConfig(TestCase):

    '''Check if config has necessary entries'''

    def create_app(self):
        '''Create the wsgi application'''
        app_ = app.create_app()
        return app_

    def test_config_values(self):
        '''Check if all required config variables are there'''
        required = ["OBJECTS_SIMBAD_TAP_URL",
                    "OBJECTS_SIMBAD_TAP_URL_CDS",
                    "OBJECTS_NED_URL",
                    "OBJECTS_NED_OBJSEARCH",
                    "OBJECTS_SIMBAD_MAX_RADIUS",
                    "OBJECTS_NED_MAX_RADIUS",
                    "OBJECTS_CACHE_TIMEOUT",
                    "OBJECTS_DEFAULT_RADIUS",
                    "OBJECTS_SIMBAD_MAX_NUMBER",
                    "OBJECTS_NED_URL",
                    "OBJECTS_SOLRQUERY_URL",
                    "API_URL"
                    ]
        missing = [x for x in required if x not in self.app.config.keys()]
        self.assertTrue(len(missing) == 0)

class TestDataRetrieval(TestCase):

    '''Check if methods return expected results'''

    def create_app(self):
        '''Create the wsgi application'''
        app_ = app.create_app()
        return app_

    @httpretty.activate
    def test_get_simbad_identifiers(self):
        '''Test to see if retrieval of SIMBAD identifiers method behaves as expected'''
        from object_service.SIMBAD import get_simbad_data
        objects = ['Andromeda','LMC']
        mockdata = {"data":[[1575544, "NAME ANDROMEDA","NAME ANDROMEDA"],[3133169, "NAME LMC", "NAME LMC"]]}
        QUERY_URL = self.app.config.get('OBJECTS_SIMBAD_TAP_URL')
        httpretty.register_uri(
            httpretty.POST, QUERY_URL,
            content_type='application/json',
            status=200,
            body='%s'%json.dumps(mockdata))
        result = get_simbad_data(objects, 'objects')
        expected = {'data': {u'LMC': {'id': '3133169', 'canonical': u'LMC'}, u'ANDROMEDA': {'id': '1575544', 'canonical': u'ANDROMEDA'}}}
        self.assertEqual(result, expected)

    @httpretty.activate
    def test_get_simbad_objects(self):
        '''Test to see if retrieval of SIMBAD objects method behaves as expected'''
        from object_service.SIMBAD import get_simbad_data
        identifiers = ["3133169", "1575544"]
        mockdata = {"data":[[1575544, "NAME ANDROMEDA","NAME ANDROMEDA"],[3133169, "NAME LMC", "NAME LMC"]]}
        QUERY_URL = self.app.config.get('OBJECTS_SIMBAD_TAP_URL')
        httpretty.register_uri(
            httpretty.POST, QUERY_URL,
            content_type='application/json',
            status=200,
            body='%s'%json.dumps(mockdata))
        result = get_simbad_data(identifiers, 'identifiers')
        expected = {'data': {u'3133169': {'id': '3133169', 'canonical': u'LMC'}, u'1575544': {'id': '1575544', 'canonical': u'ANDROMEDA'}}}
        self.assertEqual(result, expected)

    @httpretty.activate
    def test_get_ned_objects(self):
        '''Test to see if retrieval of NED objects method behaves as expected'''
        from object_service.NED import get_ned_data
        identifiers = ["LMC"]
        mockdata = {u'NameResolver': u'NED-Egret', u'Copyright': u'(C) 2017 California Institute of Technology',
                    u'Preferred': {u'Name': u'Large Magellanic Cloud'},
                    u'ResultCode': 3, u'StatusCode': 100}
        QUERY_URL = self.app.config.get('OBJECTS_NED_URL')
        httpretty.register_uri(
            httpretty.POST, QUERY_URL,
            content_type='application/json',
            status=200,
            body='%s'%json.dumps(mockdata))
        result = get_ned_data(identifiers, 'identifiers')
        expected = {'skipped': [], 'data': {u'LMC': {'id': 'LMC', 'canonical': u'Large Magellanic Cloud'}}}
        self.assertEqual(result, expected)

    @httpretty.activate
    def test_get_ned_objects_unknown_object(self):
        '''Test to see if retrieval of NED objects method behaves as expected'''
        from object_service.NED import get_ned_data
        identifiers = map(str, list(range(4)))
        def get_mock_data(v, status_code=100):
            mockdata = {u'NameResolver': u'NED-Egret',
                        u'Copyright': u'(C) 2017 California Institute of Technology',
                        u'Preferred': {u'Name': u'FOO BAR'}}
            try:
                mockdata['ResultCode'] = int(v)
            except:
                mockdata['ResultCode'] = 0
            mockdata['StatusCode'] = status_code
            return mockdata

        def request_callback(request, uri, headers):
            data = request.body
            v = json.loads(request.body)["name"]["v"]
            try:
                return (200, headers, json.dumps(get_mock_data(v)))
            except:
                return (200, headers, json.dumps(get_mock_data('0')))

        QUERY_URL = self.app.config.get('OBJECTS_NED_URL')
        httpretty.register_uri(
            httpretty.POST, QUERY_URL,
            content_type='application/json',
            status=200,
            body=request_callback)

        result = get_ned_data(identifiers, 'identifiers')
        expected = {'data': {'3': {'canonical': u'FOO BAR', 'id': '3'}},
                    'skipped': ['0','1','2']}
        self.assertEqual(result, expected)

    @httpretty.activate
    def test_get_ned_objects_unsuccessful(self):
        '''Test to see if retrieval of NED objects method behaves as expected'''
        from object_service.NED import get_ned_data
        identifiers = ["LMC"]