from __future__ import division

import warnings

import pytest

import great_expectations as ge
from great_expectations.core import (
    ExpectationConfiguration,
    ExpectationKwargs,
    ExpectationValidationResult,
)
from great_expectations.data_context.util import file_relative_path


def test_autoinspect_filedata_asset():
    #Expect an error to be raised since a file object doesn't have a columns attribute
    warnings.simplefilter('always', UserWarning)
    file_path = file_relative_path(__file__, '../test_sets/toy_data_complete.csv')
    my_file_data = ge.data_asset.FileDataAsset(file_path)

    with pytest.raises(ge.exceptions.GreatExpectationsError) as exc:
        my_file_data.profile(ge.profile.ColumnsExistProfiler)
    assert "Invalid data_asset for profiler; aborting" in exc.value.message

        # with warnings.catch_warnings(record=True):
        #     warnings.simplefilter("error")
        #     try:
        #         my_file_data.profile(ge.profile.ColumnsExistProfiler)
        #     except:
        #         raise


def test_expectation_suite_filedata_asset():
    # Load in data files
    file_path = file_relative_path(__file__, '../test_sets/toy_data_complete.csv')

    # Create FileDataAsset objects
    f_dat = ge.data_asset.FileDataAsset(file_path)

    # Set up expectations
    f_dat.expect_file_line_regex_match_count_to_equal(regex=r',\S',
                                                      expected_count=3,
                                                      skip=1, result_format="BASIC",
                                                      catch_exceptions=True)

    f_dat.expect_file_line_regex_match_count_to_be_between(regex=r',\S',
                                                           expected_max_count=2,
                                                           skip=1, result_format="SUMMARY",
                                                           include_config=True)

    # Test basic config output
    complete_config = f_dat.get_expectation_suite()
    assert [ExpectationConfiguration(
        expectation_type='expect_file_line_regex_match_count_to_equal',
        kwargs=ExpectationKwargs(
            expected_count=3,
            regex=',\\S',
            skip=1
        )
    )] == complete_config.expectations

    # Include result format kwargs
    complete_config2 = f_dat.get_expectation_suite(discard_result_format_kwargs=False,
                                                   discard_failed_expectations=False)
    assert [
        ExpectationConfiguration(expectation_type='expect_file_line_regex_match_count_to_equal',
                                 kwargs={
                                     'expected_count': 3,
                                     'regex': ',\\S',
                                     'result_format': "BASIC",
                                     'skip': 1
                                 }),
        ExpectationConfiguration(expectation_type='expect_file_line_regex_match_count_to_be_between',
                                 kwargs={
                                     'expected_max_count': 2,
                                     'regex': ',\\S',
                                     'result_format': 'SUMMARY',
                                     'skip': 1
                                 })
        ] == complete_config2.expectations

    # Discard Failing Expectations
    complete_config3 = f_dat.get_expectation_suite(discard_result_format_kwargs=False,
                                                   discard_failed_expectations=True)

    assert [ExpectationConfiguration(expectation_type='expect_file_line_regex_match_count_to_equal',
                                     kwargs={'expected_count': 3,
                                             'regex': ',\\S',
                                             'result_format': 'BASIC',
                                             'skip': 1
                                             }
                                     )] == complete_config3.expectations


def test_file_format_map_output():
    incomplete_file_path = file_relative_path(__file__, '../test_sets/toy_data_incomplete.csv')
    incomplete_file_dat = ge.data_asset.FileDataAsset(incomplete_file_path)
    null_file_path = file_relative_path(__file__, '../test_sets/null_file.csv')
    null_file_dat = ge.data_asset.FileDataAsset(null_file_path)
    white_space_path = file_relative_path(__file__, '../test_sets/white_space.txt')
    white_space_dat = ge.data_asset.FileDataAsset(white_space_path)

    # Boolean Expectation Output
    expectation = incomplete_file_dat.expect_file_line_regex_match_count_to_equal(regex=r',\S',
                                                                                  expected_count=3,
                                                                                  skip=1,
                                                                                  result_format="BOOLEAN_ONLY",
                                                                                  include_config=False)
    expected_result = ExpectationValidationResult(success=False)
    assert expected_result == expectation

    # Empty File Expectations
    expectation = null_file_dat.expect_file_line_regex_match_count_to_equal(regex=r',\S',
                                                                            expected_count=3,
                                                                            skip=1,
                                                                            result_format="BASIC",
                                                                            include_config=False)
    expected_result = ExpectationValidationResult(
        success=None,
        result={
            "element_count": 0, "missing_count": 0, "missing_percent": None, "unexpected_count": 0,
            "unexpected_percent": None, "unexpected_percent_nonmissing": None, "partial_unexpected_list": []
        }
    )

    assert expected_result == expectation

    # White Space File
    expectation = white_space_dat.expect_file_line_regex_match_count_to_equal(regex=r',\S',
                                                                              expected_count=3,
                                                                              result_format="BASIC",
                                                                              include_config=False)
    expected_result = ExpectationValidationResult(
        success=None,
        result={
            "element_count": 11, "missing_count": 11, "missing_percent": 100.0, "unexpected_count": 0,
            "unexpected_percent": 0, "unexpected_percent_nonmissing": None, "partial_unexpected_list": []
        }
    )

    assert expected_result == expectation

    # Complete Result Format
    expectation = incomplete_file_dat.expect_file_line_regex_match_count_to_equal(regex=r',\S',
                                                                                  expected_count=3,
                                                                                  skip=1,
                                                                                  result_format="COMPLETE",
                                                                                  include_config=False)

    expected_result = ExpectationValidationResult(
        success=False,
        result={
            "element_count": 9, "missing_count": 2, "missing_percent": (2/9 * 100), "unexpected_count": 3,
            "unexpected_percent": (3/9 * 100), "unexpected_percent_nonmissing": (3/7 * 100),
            "partial_unexpected_list": ['A,C,1\n', 'B,1,4\n', 'A,1,4\n'],
            "partial_unexpected_counts": [
                {"value": 'A,1,4\n', "count": 1},
                {"value": 'A,C,1\n', "count": 1},
                {"value": 'B,1,4\n', "count": 1}],
            "partial_unexpected_index_list": [0, 3, 5],
            "unexpected_list": ['A,C,1\n', 'B,1,4\n', 'A,1,4\n'],
            "unexpected_index_list": [0, 3, 5]
        }
    )

    assert expected_result == expectation

    # Invalid Result Format
    with pytest.raises(ValueError):
        expectation = incomplete_file_dat.expect_file_line_regex_match_count_to_equal(regex=r',\S',
                                                                                      expected_count=3,
                                                                                      skip=1,
                                                                                      result_format="JOKE",
                                                                                      include_config=False)
