# (c) cavaliba.com - tests / pipeline

import yaml

from django.test import TestCase
from django.core.cache import cache as cache_django

from tests import helper

import app_home.cache as cache

from app_data.loader import load_broker

from app_data.pipeline import Pipeline


class PipelineCRUD(TestCase):

    fixtures = ["init"]

    def setUp(self):
        helper.add_admin_user(login="unittest")
        cache.clear()
        cache_django.clear()


    def test_list_pipelines(self):

        pipelines = Pipeline.list()
        self.assertEqual(len(pipelines), 5)


    def test_create_pipeline(self):

        helper.add_pipeline_noop()
        pipelines = Pipeline.list()
        self.assertEqual(len(pipelines), 6)


    def test_pipeline_from_name(self):

        helper.add_pipeline_noop()
        pipeline = Pipeline.from_name("pipeline_noop")
        self.assertIsNotNone(pipeline)
        self.assertEqual(pipeline.keyname, "pipeline_noop")
        self.assertEqual(pipeline.tasks, ["field_noop"])


    def test_pipeline_not_found(self):

        pipeline = Pipeline.from_name("does_not_exist")
        self.assertIsNone(pipeline)


    def test_create_pipeline_disabled(self):

        pipelines = Pipeline.list(is_enabled=True)
        self.assertEqual(len(pipelines), 5)

        helper.add_pipeline_noop()

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest2
              displayname: unittest_pipeline
              description: unittest pipeline
              is_enabled: False
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks:
                  - field_noop
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        pipelines = Pipeline.list(is_enabled=False)
        self.assertEqual(len(pipelines), 1)

        pipelines = Pipeline.list(is_enabled=True)
        self.assertEqual(len(pipelines), 6)



    # primitives with schema

    def test_pipeline_discard(self):

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks:
                  - discard: ['']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        pipeline = Pipeline.from_name("unittest")
        datalist = [
            {'a':5, 'b':6},
            {'a':'unit', 'b':'test'},
        ]
        kept = [d for d in datalist if pipeline.apply(d) != 'discard']
        self.assertEqual(len(kept), 0)


    def test_pipeline_condition(self):

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks:
                  - set_condition: ['CONDITION_TEST', field_match, a, 'test']
                  - field_set: ['CONDITION_TEST', b, 'testok']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        pipeline = Pipeline.from_name("unittest")
        datadict = {'a':'test'}
        pipeline.apply(datadict)
        self.assertIn('a', datadict)
        self.assertIn('b', datadict)
        self.assertEqual(datadict['b'], 'testok')


    def test_pipeline_condition_negate(self):

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks:
                  - set_condition: [CONDITION_TEST, field_match, a, 'test']
                  - field_set: ['!CONDITION_TEST', b, 'testok']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        pipeline = Pipeline.from_name("unittest")
        datadict = {'a':'unit'}
        pipeline.apply(datadict)
        self.assertIn('a', datadict)
        self.assertIn('b', datadict)
        self.assertEqual(datadict['b'], 'testok')


    def test_pipeline_condition_reset_to_false(self):
        # set_condition should reset to false when condition no longer matches

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks:
                  - set_condition: [COND, field_match, a, 'yes']
                  - set_condition: [COND, field_match, b, 'yes']
                  - field_set: [COND, c, 'shouldnotbeset']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        pipeline = Pipeline.from_name("unittest")
        # a='yes' sets COND true, b='no' resets COND to false => field_set must not run
        datadict = {'a': 'yes', 'b': 'no'}
        pipeline.apply(datadict)
        self.assertNotIn('c', datadict)


    def test_pipeline_condition_set_then_true(self):
        # set_condition evaluates false first, then true => task must run

        datalist = yaml.safe_load('''
            - classname: _pipeline
              keyname: unittest
              displayname: unittest_pipeline
              description: unittest pipeline
              content: |
                  csv_delimiter: '|'
                  classname: test1
                  keyfield: keyname
                  tasks:
                  - set_condition: [COND, field_match, a, 'yes']
                  - set_condition: [COND, field_match, b, 'yes']
                  - field_set: [COND, c, 'shouldbeset']
            ''')
        aaa = {'perms':['p_pipeline_create']}
        load_broker(datalist=datalist, aaa=aaa)

        pipeline = Pipeline.from_name("unittest")
        # a='no' keeps COND false, b='yes' sets COND true => field_set must run
        datadict = {'a': 'no', 'b': 'yes'}
        pipeline.apply(datadict)
        self.assertIn('c', datadict)
        self.assertEqual(datadict['c'], 'shouldbeset')
