# -*- coding: utf-8 -*-
import io
import string

from obspy import UTCDateTime
from obspy.io.xseed.fields import Float, VariableString, FixedString
import pytest


class TestFields():
    """
    Fields test suite.
    """
    def test_format_exponential(self):
        field = Float(1, "test", 12, mask='%+1.5e', strict=True)
        assert field.write('2.5') == b'+2.50000E+00'

    def test_read_date_time(self):
        field = VariableString(1, "test", 1, 22, 'T', strict=True)
        # 1
        orig = b'1992,002,00:00:00.0000~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(1992, 1, 2)
        assert field.write(dt) == b'1992,002~'
        # 1
        orig = b'1992,002~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(1992, 1, 2)
        assert field.write(dt) == b'1992,002~'
        # 2
        orig = b'1992,005,01:02:03.4567~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(1992, 1, 5, 1, 2, 3, 456700)
        assert field.write(dt) == orig
        # 3
        orig = b'1992,005,01:02:03.0001~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(1992, 1, 5, 1, 2, 3, 100)
        assert field.write(dt) == orig
        # 4
        orig = b'1992,005,01:02:03.1000~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(1992, 1, 5, 1, 2, 3, 100000)
        assert field.write(dt) == orig
        # 5
        orig = b'1987,023,04:23:05.1~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(1987, 1, 23, 4, 23, 5, 100000)
        assert field.write(dt) == b'1987,023,04:23:05.1000~'
        # 6
        orig = b'1987,023,04:23:05.123~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(1987, 1, 23, 4, 23, 5, 123000)
        assert field.write(dt) == b'1987,023,04:23:05.1230~'
        #
        orig = b'2008,358,01:30:22.0987~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 1, 30, 22, 98700)
        assert field.write(dt) == orig
        #
        orig = b'2008,358,01:30:22.9876~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 1, 30, 22, 987600)
        assert field.write(dt) == orig
        #
        orig = b'2008,358,01:30:22.0005~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 1, 30, 22, 500)
        assert field.write(dt) == orig
        #
        orig = b'2008,358,01:30:22.0000~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 1, 30, 22, 0)
        assert field.write(dt) == orig

    def test_read_compact_date_time(self):
        field = VariableString(1, "test", 0, 22, 'T', strict=True,
                               compact=True)
        # 1
        orig = b'1992,002~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(1992, 1, 2)
        assert field.write(dt) == orig
        # 2
        orig = b'2007,199~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2007, 7, 18)
        assert field.write(dt) == orig
        # 3 - wrong syntax
        orig = b'1992'
        with pytest.raises(Exception):
            field.read(io.BytesIO(orig))
        orig = b'1992,'
        with pytest.raises(Exception):
            field.read(io.BytesIO(orig))
        orig = b'1992~'
        with pytest.raises(Exception):
            field.read(io.BytesIO(orig))
        orig = b'1992,~'
        with pytest.raises(Exception):
            field.read(io.BytesIO(orig))
        # 5 - empty datetime
        orig = b'~'
        dt = field.read(io.BytesIO(orig))
        assert dt == ''
        assert field.write(dt) == b'~'
        # 6 - bad syntax
        orig = b''
        with pytest.raises(Exception):
            field.read(io.BytesIO(orig))
        assert field.write(dt) == b'~'
        # 7
        orig = b'2007,199~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2007, 7, 18)
        assert field.write(dt) == b'2007,199~'
        # 8
        orig = b'2009,074,12~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2009, 3, 15, 12)
        assert field.write(dt) == orig
        # 9
        orig = b'2008,358,01:30:22.0012~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 1, 30, 22, 1200)
        assert field.write(dt) == orig
        #
        orig = b'2008,358,00:00:22~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 0, 0, 22, 0)
        assert field.write(dt) == orig
        #
        orig = b'2008,358,00:30~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 0, 30, 0, 0)
        assert field.write(dt) == orig
        #
        orig = b'2008,358,01~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 1, 0, 0, 0)
        assert field.write(dt) == orig
        #
        orig = b'2008,358~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 0, 0, 0, 0)
        assert field.write(dt) == orig
        #
        orig = b'2008,358,01:30:22.5~'
        dt = field.read(io.BytesIO(orig))
        assert dt == UTCDateTime(2008, 12, 23, 1, 30, 22, 500000)
        assert field.write(dt) == b'2008,358,01:30:22.5000~'

    def test_wrong_spaces(self):
        """
        VariableString(..., 'S') should remove leading or trailing spaces.
        """
        field = VariableString(1, "test", 1, 60, 'UNLPS', strict=True)
        orig = b' T3930_b A6689 3930 ~'
        result = field.read(io.BytesIO(orig))
        assert result == 'T3930_b A6689 3930'

    def test_fixed_string_any_punctuation(self):
        """
        FixedString(..., 'P') should allow any punctuation character.
        """
        field = FixedString(1, "test", 9, 'UP')
        for character in string.punctuation:
            orig = b'ABC' + character.encode("utf-8") + b'DEF'
            result = field.read(io.BytesIO(orig))
            assert result == 'ABC' + character + 'DEF'

    def test_variable_string_any_punctuation(self):
        """
        VariableString(..., 'P') should allow any punctuation character.
        """
        field = VariableString(1, "test", 1, 30, 'UP')
        for character in string.punctuation:
            # need to skip tilde as it is also the end marker of a variable
            # field
            if character == '~':
                continue
            orig = b'ABC' + character.encode("utf-8") + b'DEF~'
            result = field.read(io.BytesIO(orig))
            assert result == 'ABC' + character + 'DEF'
