import textwrap
import pytest
import sys
import os

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from canesm.util import ProcessBash, ProcessCPPDef


class TestProcessBash:

    def test_basic(self):

        bash = textwrap.dedent("""
        ###################
        #    test bash
        ###################
        
        abc = 1     # comment here
        bcd=1
        
        my_abc=1
         my_bcd = 1
         
         efg =1        ! comment here efg
         #def=1    
         
        fgh = 1   
        fgh = $fgh
        
        hij=1
        """)

        settings = {'abc': 2, 'bcd': 2, 'efg': 2, 'fgh': 2}
        bash_out = textwrap.dedent("""
        ###################
        #    test bash
        ###################
        
        abc =2
        bcd=2
        
        my_abc=1
         my_bcd = 1
         
         efg =2
         #def=1    
                 
        fgh =2
        fgh = $fgh
        
        hij=1
        """)
        line = ProcessBash(bash).process(settings)
        assert line == bash_out

        bash = " abc = 1     ! abc = 1\n"
        line = ProcessBash(bash).process({'abc': 2})
        assert line == " abc =2\n"

        bash = " abc = 1     # comment here abc = 1\n"
        line = ProcessBash(bash).process({'abc': 2})
        assert line == " abc =2\n"

        bash = "#def=5"
        with pytest.raises(ValueError):
            ProcessBash(bash).process({'def': 6})

        bash = "      sgbot=0.995               ! bottom full levels (0.995~995hPa)\n" \
               "      shbot=0.995               ! bottom half levels (0.995~995hPa)\n"
        line = ProcessBash(bash).process({'sgbot': 1.01})
        assert line == "      sgbot=1.01\n      shbot=0.995               ! bottom half levels (0.995~995hPa)\n"

        bash = "      sgdampt_p=0.010           ! reduction factor from sgfull to sgtop (0.01=1%)"
        line = ProcessBash(bash).process({'sgdampt_p': 0.020})
        assert line == "      sgdampt_p=0.02"

        bash = "&vtau_scale\n" \
               "       !--- VTAU scale parameters: VOL_scaled = scale * VOL\n" \
               "       vtau_scale_use=0      ! turn on scaling\n" \
               "       vtau_lwe_scale=$vtau_scale\n" \
               "       vtau_swe_scale=$vtau_scale"
        line = ProcessBash(bash).process({'vtau_scale_use': 1})
        assert line == "&vtau_scale\n" \
                       "       !--- VTAU scale parameters: VOL_scaled = scale * VOL\n" \
                       "       vtau_scale_use=1\n" \
                       "       vtau_lwe_scale=$vtau_scale\n" \
                       "       vtau_swe_scale=$vtau_scale"

    def test_unknown_param(self):

        bash = '#\nabc=1'
        with pytest.raises(ValueError):
            ProcessBash(bash).process({'abd': 2})

    def test_multivar_line(self):

        bash = "#\nabc=1; bcd=2\n"
        line = ProcessBash(bash).process({'abc': 2})
        assert line == "#\nabc=2; bcd=2\n"

        bash = "#\nabc=1; bcd=2\n"
        line = ProcessBash(bash).process({'bcd': 1})
        assert line == "#\nabc=1; bcd=1\n"

        bash = " abc=1 ; bcd =  2;"
        line = ProcessBash(bash).process({'abc': 2, 'bcd': 4})
        assert line == " abc=2; bcd =4;"

        bash = " abc=1; \n"
        with pytest.raises(ValueError):
            line = ProcessBash(bash).process({'abc': 2, 'bcd': 4})

    def test_variable_sub(self):

        bash = '#\nabc=1\n varname=$ghg_scale\nvarname2=$ghg_scale\nvarname5=ghg_scale'
        line = ProcessBash(bash).process({'$ghg_scale': 8})
        assert line == '#\nabc=1\n varname=8\nvarname2=8\nvarname5=ghg_scale'

        bash = '#\nabc=1\n varname=$ghg_scale     ! comment here\nvarname2=$ghg_scale\nvarname5=ghg_scale'
        line = ProcessBash(bash).process({'$ghg_scale': 8})
        assert line == '#\nabc=1\n varname=8     ! comment here\nvarname2=8\nvarname5=ghg_scale'

        bash = '#\nabc=1\n varname=$ghg_scale     # comment here\nvarname2=$ghg_scale\nvarname5=ghg_scale'
        line = ProcessBash(bash).process({'$ghg_scale': 8})
        assert line == '#\nabc=1\n varname=8     # comment here\nvarname2=8\nvarname5=ghg_scale'

        bash = '#\nabc=1\n varname=$ghg_scale\nvarname2=$ghg_scale\nvarname5=ghg_scale'
        with pytest.raises(ValueError):
            ProcessBash(bash).process({'$gh_scale': 8})

        bash = "&vtau_scale\n" \
               "       !--- VTAU scale parameters: VOL_scaled = scale * VOL\n" \
               "       vtau_scale_use=0\n" \
               "       vtau_lwe_scale=$vtau_scale\n" \
               "       vtau_swe_scale=$vtau_scale"
        line = ProcessBash(bash).process({'$vtau_scale': 1.1})
        assert line == "&vtau_scale\n" \
                       "       !--- VTAU scale parameters: VOL_scaled = scale * VOL\n" \
                       "       vtau_scale_use=0\n" \
                       "       vtau_lwe_scale=1.1\n" \
                       "       vtau_swe_scale=1.1"

        bash = "&temi_scale\n" \
               "       !--- TEMI scale parameters: AER_scaled = scale * AER\n" \
               "       temi_scale_use=0          ! =0, do not rescale TEMI forcing, =1, rescale TEMI\n" \
               "       temi_ssfc_scale=$temi_scale       ! surface emissions\n" \
               "       temi_sstk_scale=$temi_scale       ! stack (power plant) emissions"
        line = ProcessBash(bash).process({'$temi_scale': 1.1})
        assert line == "&temi_scale\n" \
                       "       !--- TEMI scale parameters: AER_scaled = scale * AER\n" \
                       "       temi_scale_use=0          ! =0, do not rescale TEMI forcing, =1, rescale TEMI\n" \
                       "       temi_ssfc_scale=1.1       ! surface emissions\n" \
                       "       temi_sstk_scale=1.1       ! stack (power plant) emissions"


class TestProcessCPPDef:

    def test_basic(self):

        bash = "\n#undef radforce\n"
        line = ProcessCPPDef(bash).process({'radforce': True})
        assert line == '\n#define radforce\n'

        bash = "\n #define radforce"
        line = ProcessCPPDef(bash).process({'radforce': False})
        assert line == '\n#undef radforce'

        bash = "\n#define abcd\n"
        line = ProcessCPPDef(bash).process({'radforce': False})
        assert line == '\n#define abcd\n\n#undef radforce'


if __name__ == '__main__':
    TestProcessBash().test_variable_sub()
    TestProcessBash().test_basic()
    TestProcessBash().test_multivar_line()
    TestProcessBash().test_unknown_param()
