# coding: utf-8
#
# Copyright 2014 The Oppia Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__author__ = 'Jeremy Emerson'

from core.domain import exp_domain
from core.domain import exp_services
from core.domain import rule_domain
from core.domain import stats_domain
from core.domain import stats_services

import test_utils


class EventHandlerUnitTests(test_utils.GenericTestBase):
    """Test the event handler methods."""

    DEFAULT_RULESPEC_STR = exp_domain.DEFAULT_RULESPEC_STR
    SUBMIT_HANDLER = stats_services.SUBMIT_HANDLER_NAME

    def test_record_state_hit(self):
        stats_services.EventHandler.record_state_hit('eid', 'sname', True)

        counter = stats_domain.StateCounter.get('eid', 'sname')
        self.assertEquals(counter.first_entry_count, 1)
        self.assertEquals(counter.subsequent_entries_count, 0)
        self.assertEquals(counter.resolved_answer_count, 0)
        self.assertEquals(counter.active_answer_count, 0)
        self.assertEquals(counter.total_entry_count, 1)
        self.assertEquals(counter.no_answer_count, 1)

        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR)
        self.assertEquals(answer_log.answers, {})

        stats_services.EventHandler.record_state_hit('eid', 'sname', False)

        counter = stats_domain.StateCounter.get('eid', 'sname')
        self.assertEquals(counter.first_entry_count, 1)
        self.assertEquals(counter.subsequent_entries_count, 1)
        self.assertEquals(counter.resolved_answer_count, 0)
        self.assertEquals(counter.active_answer_count, 0)
        self.assertEquals(counter.total_entry_count, 2)
        self.assertEquals(counter.no_answer_count, 2)

        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR)
        self.assertEquals(answer_log.answers, {})

    def test_record_answer_submitted(self):
        stats_services.EventHandler.record_state_hit('eid', 'sname', True)
        stats_services.EventHandler.record_answer_submitted(
            'eid', 'sname', self.SUBMIT_HANDLER, 'Rule', 'answer')

        counter = stats_domain.StateCounter.get('eid', 'sname')
        self.assertEquals(counter.first_entry_count, 1)
        self.assertEquals(counter.subsequent_entries_count, 0)
        self.assertEquals(counter.total_entry_count, 1)
        self.assertEquals(counter.resolved_answer_count, 0)
        self.assertEquals(counter.active_answer_count, 1)
        self.assertEquals(counter.no_answer_count, 0)

        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, 'Rule')
        self.assertEquals(answer_log.answers, {'answer': 1})

        stats_services.EventHandler.record_state_hit('eid', 'sname', False)
        stats_services.EventHandler.record_answer_submitted(
            'eid', 'sname', self.SUBMIT_HANDLER, 'Rule', 'answer')

        counter = stats_domain.StateCounter.get('eid', 'sname')
        self.assertEquals(counter.first_entry_count, 1)
        self.assertEquals(counter.subsequent_entries_count, 1)
        self.assertEquals(counter.total_entry_count, 2)
        self.assertEquals(counter.resolved_answer_count, 0)
        self.assertEquals(counter.active_answer_count, 2)
        self.assertEquals(counter.no_answer_count, 0)

        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, 'Rule')
        self.assertEquals(answer_log.answers, {'answer': 2})

        stats_services.EventHandler.record_state_hit('eid', 'sname', False)

        counter = stats_domain.StateCounter.get('eid', 'sname')
        self.assertEquals(counter.first_entry_count, 1)
        self.assertEquals(counter.subsequent_entries_count, 2)
        self.assertEquals(counter.total_entry_count, 3)
        self.assertEquals(counter.resolved_answer_count, 0)
        self.assertEquals(counter.active_answer_count, 2)
        self.assertEquals(counter.no_answer_count, 1)

        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, 'Rule')
        self.assertEquals(answer_log.answers, {'answer': 2})

    def test_resolve_answers_for_default_rule(self):
        stats_services.EventHandler.record_state_hit('eid', 'sname', True)

        # Submit three answers.
        stats_services.EventHandler.record_answer_submitted(
            'eid', 'sname', self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR,
            'a1')
        stats_services.EventHandler.record_answer_submitted(
            'eid', 'sname', self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR,
            'a2')
        stats_services.EventHandler.record_answer_submitted(
            'eid', 'sname', self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR,
            'a3')

        counter = stats_domain.StateCounter.get('eid', 'sname')
        self.assertEquals(counter.resolved_answer_count, 0)
        self.assertEquals(counter.active_answer_count, 3)

        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR)
        self.assertEquals(
            answer_log.answers, {'a1': 1, 'a2': 1, 'a3': 1})

        # Nothing changes if you try to resolve an invalid answer.
        stats_services.EventHandler.resolve_answers_for_default_rule(
            'eid', 'sname', self.SUBMIT_HANDLER, ['fake_answer'])
        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR)
        self.assertEquals(
            answer_log.answers, {'a1': 1, 'a2': 1, 'a3': 1})

        # Resolve two answers.
        stats_services.EventHandler.resolve_answers_for_default_rule(
            'eid', 'sname', self.SUBMIT_HANDLER, ['a1', 'a2'])

        counter = stats_domain.StateCounter.get('eid', 'sname')
        self.assertEquals(counter.resolved_answer_count, 2)
        self.assertEquals(counter.active_answer_count, 1)

        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR)
        self.assertEquals(answer_log.answers, {'a3': 1})

        # Nothing changes if you try to resolve an answer that has already
        # been resolved.
        stats_services.EventHandler.resolve_answers_for_default_rule(
            'eid', 'sname', self.SUBMIT_HANDLER, ['a1'])
        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR)
        self.assertEquals(answer_log.answers, {'a3': 1})

        # Resolve the last answer.
        stats_services.EventHandler.resolve_answers_for_default_rule(
            'eid', 'sname', self.SUBMIT_HANDLER, ['a3'])

        counter = stats_domain.StateCounter.get('eid', 'sname')
        self.assertEquals(counter.resolved_answer_count, 3)
        self.assertEquals(counter.active_answer_count, 0)

        answer_log = stats_domain.StateRuleAnswerLog.get(
            'eid', 'sname', self.SUBMIT_HANDLER, 'Rule')
        self.assertEquals(answer_log.answers, {})


class StatsServicesUnitTests(test_utils.GenericTestBase):
    """Test the statistics services."""

    DEFAULT_RULESPEC_STR = exp_domain.DEFAULT_RULESPEC_STR
    SUBMIT_HANDLER = stats_services.SUBMIT_HANDLER_NAME