# This file is part of the ISIS IBEX application.
# Copyright (C) 2012-2016 Science & Technology Facilities Council.
# All rights reserved.
#
# This program is distributed in the hope that it will be useful.
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v1.0 which accompanies this distribution.
# EXCEPT AS EXPRESSLY SET FORTH IN THE ECLIPSE PUBLIC LICENSE V1.0, THE PROGRAM
# AND ACCOMPANYING MATERIALS ARE PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
# OR CONDITIONS OF ANY KIND.  See the Eclipse Public License v1.0 for more details.
#
# You should have received a copy of the Eclipse Public License v1.0
# along with this program; if not, you can obtain a copy from
# https://www.eclipse.org/org/documents/epl-v10.php or
# http://opensource.org/licenses/eclipse-1.0.php
import os
from unittest import TestCase

from datetime import timedelta
from hamcrest import *
from mock import Mock

from ArchiverAccess.archive_access_configuration import DEFAULT_LOGGING_PERIOD_IN_S, DEFAULT_LOG_PATH
from ArchiverAccess.archive_access_config_builder import ArchiverAccessDatabaseConfigBuilder
from ArchiverAccess.test_modules.stubs import ArchiverDataStub


class TestDatabaseConfigBuilder(TestCase):

    def test_GIVEN_ioc_name_WHEN_generate_THEN_configuration_with_correct_file_name_template_is_created(self):
        ioc_name = "myioc"
        expected_filename_template = os.path.join(DEFAULT_LOG_PATH, "myioc", "myioc_{start_time}.dat")
        expected_continous_filename_template = os.path.join(DEFAULT_LOG_PATH, "myioc",
                                                            "myioc_{start_time}_continuous.dat")
        ioc_data_source = self._create_ioc_data_source(ioc_name=ioc_name)
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)

        config = db_config_builder.create()

        assert_that(config[0].on_end_logging_filename_template, is_(expected_filename_template))
        assert_that(config[0].continuous_logging_filename_template, is_(expected_continous_filename_template))

    def test_GIVEN_header_line_in_database_WHEN_generate_THEN_configuration_is_created(self):
        expected_header_line = "expected_header_line a line of goodness :-)"
        ioc_data_source = self._create_ioc_data_source(header_lines=[expected_header_line])
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)

        config = db_config_builder.create()

        assert_that(config, has_length(1))
        assert_that(config[0].header, is_([expected_header_line]))

    def test_GIVEN_templated_header_line_in_database_WHEN_generate_THEN_configuration_is_created(self):
        pv_name = "pv:name"
        expected_pv_name = pv_name + ".VAL"
        header_line = "Header line with pv {this_pv}"
        expected_header_line = header_line.format(this_pv="{0}")
        ioc_data_source = self._create_ioc_data_source(header_lines=[header_line], header_pvs=[pv_name])
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)

        config = db_config_builder.create()

        assert_that(config, has_length(1))
        assert_that(config[0].header, is_([expected_header_line]))
        assert_that(config[0].pv_names_in_header, is_([expected_pv_name]))

    def test_GIVEN_multiple_header_line_in_database_WHEN_generate_THEN_configuration_is_created(self):
        expected_header_lines = ["line 1", "line2", "line3"]
        ioc_data_source = self._create_ioc_data_source(header_lines=expected_header_lines)
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)

        config = db_config_builder.create()

        assert_that(config, has_length(1))
        assert_that(config[0].header, is_(expected_header_lines))

    def test_GIVEN_multiple_header_line_in_funny_order_with_repeated_indexes_and_different_cases_WHEN_generate_THEN_configuration_is_created(self):
        expected_header_lines = ["line 1", "line2", "line3", "line4"]
        header_lines_section = [("pvname", "LoG_header6", expected_header_lines[3]),
                                ("pvname", "LOG_header4", expected_header_lines[1]),
                                ("pvname", "LOG_Header1", expected_header_lines[0]),
                                ("pvname", "LOG_header4", expected_header_lines[2])]

        ioc_data_source = self._create_ioc_data_source(header_lines_section=header_lines_section)
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)

        config = db_config_builder.create()

        assert_that(config, has_length(1))
        assert_that(config[0].header, is_(expected_header_lines))

    def test_GIVEN_trigger_pv_only_marked_WHEN_generate_THEN_configuration_has_trigger_pv_in(self):
        expected_trigger_pv = "inst:triggerpv.val"
        ioc_data_source = self._create_ioc_data_source(trigger_pv=expected_trigger_pv, trigger_pv_template="")
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)

        config = db_config_builder.create()

        assert_that(config[0].trigger_pv, is_(expected_trigger_pv))

    def test_GIVEN_trigger_pv_is_templated_WHEN_generate_THEN_configuration_has_trigger_pv_in(self):
        expected_trigger_pv = "inst:triggerpv.val"
        ioc_data_source = self._create_ioc_data_source(trigger_pv=expected_trigger_pv)
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)

        config = db_config_builder.create()

        assert_that(config[0].trigger_pv, is_(expected_trigger_pv))

    def test_GIVEN_trigger_pv_is_explicit_WHEN_generate_THEN_configuration_has_trigger_pv_in(self):
        trigger_pv = "diff:triggerpv"
        expected_trigger_pv = trigger_pv + ".VAL"
        ioc_data_source = self._create_ioc_data_source(trigger_pv="blah", trigger_pv_template=trigger_pv)
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)

        config = db_config_builder.create()

        assert_that(config[0].trigger_pv, is_(expected_trigger_pv))

    def test_GIVEN_logging_period_pv_is_only_marked_WHEN_generate_THEN_configuration_has_logging_period_pv(self):
        period_pv = "diff:triggerpv.VAL"
        ioc_data_source = self._create_ioc_data_source(period_pv=period_pv, period_pv_template="")
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)
        log_period = 10
        expected_log_period = timedelta(seconds=log_period)
        archive_data_source = ArchiverDataStub(initial_values={period_pv: log_period})

        config = db_config_builder.create()

        logging_period = config[0].logging_period_provider.get_logging_period(archive_data_source, None)
        assert_that(logging_period, is_(expected_log_period))

    def test_GIVEN_logging_period_pv_is_templated_WHEN_generate_THEN_configuration_has_logging_period_pv(self):
        period_pv = "diff:triggerpv"
        ioc_data_source = self._create_ioc_data_source(period_pv=period_pv, period_pv_template="this_pv")
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)
     
   log_period = 10
        expected_log_period = timedelta(seconds=log_period)
        archive_data_source = ArchiverDataStub(initial_values={period_pv + ".VAL": log_period})

        config = db_config_builder.create()

        logging_period = config[0].logging_period_provider.get_logging_period(archive_d
ata_source, None)
        assert_that(logging_period, is_(expected_log_period))

    def test_GIVEN_logging_period_pv_is_explicit_WHEN_generate_THEN_configuration_has_logging_period_pv(self):
        period_pv = "diff:triggerpv.field"
        ioc_data_source = self._create_ioc_data_source(period_pv="blah", period_pv_template=period_pv)
        db_config_builder = ArchiverAccessDatabaseConfigBuilder(ioc_data_source)
        log_period = 10
        expected_log_period = timedelta(seconds=log_period)
        archive_data_source = ArchiverDataStub(initial_values={period_pv: log_period})

        config = db_config_builder.create()

        logging_period = config[0].logging_period_provider.get_logging_period(archive_dat