##########################################################################################
# pdsparser/test_labels.py
##########################################################################################

import datetime
import pathlib
import sys
import unittest

from filecache import FCPath
from pdsparser import Pds3Label

ROOT_DIR = pathlib.Path(sys.modules['pdsparser'].__file__).parent.parent
TEST_FILE_DIR = ROOT_DIR / 'test_files'

MAXDIFF = 300

class Test_labels(unittest.TestCase):

    def test_COVIMS_0xxx(self):

        self.maxDiff = MAXDIFF

        # This file has an un-quoted N/A, so method='loose'
        root = 'v1877838443_1'
        filepath = TEST_FILE_DIR / (root + '.lbl')
        d1 = Pds3Label(filepath, method='loose', types=True, sources=True, expand=False)
        answer = (TEST_FILE_DIR / (root + '-lbl-answer.txt')).read_text()
        answer_dict = eval(answer)
        self.assertEqual(d1.dict, answer_dict)

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True, expand=False)
        self.assertEqual(d2.dict, answer_dict)

        # test repairs, change strict to True
        d1 = Pds3Label(filepath, method='strict', types=True, sources=True, expand=False,
                       repairs=(r'(?<!["\'])N/A', "'N/A'"))
        for key in ('GAIN_MODE_ID_source',  'BACKGROUND_SAMPLING_MODE_ID_source'):
            answer_dict[key] = answer_dict[key].replace('N/A', "'N/A'")
        self.assertEqual(d1.dict, answer_dict)

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True, expand=False,
                       repairs=(r'(?<!["\'])N/A', "'N/A'"))
        self.assertEqual(d2.dict, answer_dict)

        # expand=True
        d1 = Pds3Label(filepath, method='loose', types=True, sources=True, expand=True)
        answer = (TEST_FILE_DIR / (root + '-lbl-expanded.txt')).read_text()
        answer_dict = eval(answer)
        self.assertEqual(d1.dict, answer_dict)

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True, expand=True)
        self.assertEqual(d2.dict, answer_dict)

        d1 = Pds3Label(filepath, method='strict', types=True, sources=True, expand=True,
                       repairs=(r'(?<!["\'])N/A', "'N/A'"))
        for key in ('GAIN_MODE_ID_source',  'BACKGROUND_SAMPLING_MODE_ID_source'):
            answer_dict[key] = answer_dict[key].replace('N/A', "'N/A'")
        self.assertEqual(d1.dict, answer_dict)

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True, expand=True,
                       repairs=(r'(?<!["\'])N/A', "'N/A'"))
        self.assertEqual(d2.dict, answer_dict)

        # label from qub
        filepath = TEST_FILE_DIR / (root + '.qub')
        d1 = Pds3Label(filepath, method='strict', types=True, sources=True)
        answer = (TEST_FILE_DIR / (root + '-qub-answer.txt')).read_text()
        answer_dict = eval(answer)
        self.assertEqual(d1.dict, answer_dict)

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True)
        self.assertEqual(d2.dict, answer_dict)

    def test_GOxxx_v1(self):

        self.maxDiff = MAXDIFF

        root = 'C052079-2800R'
        filepath = TEST_FILE_DIR / (root + '.LBL')
        d1 = Pds3Label(filepath, method='loose', types=True, sources=True, expand=False)
        answer = (TEST_FILE_DIR / (root + '-answer.txt')).read_text()
        self.assertEqual(d1.dict, eval(answer))

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True, expand=False)
        self.assertEqual(d2.dict, eval(answer))

        d1 = Pds3Label(filepath, method='loose', types=True, sources=True, expand=True)
        answer = (TEST_FILE_DIR / (root + '-expanded.txt')).read_text()
        self.assertEqual(d1.dict, eval(answer))

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True, expand=True)
        self.assertEqual(d2.dict, eval(answer))

    def text_JNOJIR_xxxx(self):

        self.maxDiff = MAXDIFF

        root = 'JIR_LOG_SPE_RDR_2020048T195001_V01'
        filepath = TEST_FILE_DIR / (root + '.LBL')
        d1 = Pds3Label(filepath, method='strict', types=True, sources=True)
        answer = (TEST_FILE_DIR / (root + '-answer.txt')).read_text()
        self.assertEqual(d1.dict, eval(answer))

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True)
        self.assertEqual(d2.dict, eval(answer))

    def text_JNOJNC_0xxx(self):

        self.maxDiff = MAXDIFF

        root = 'JNCE_2022348_47C00007_V01'
        filepath = TEST_FILE_DIR / (root + '.LBL')
        d1 = Pds3Label(filepath, method='strict', types=True, sources=True)
        answer = (TEST_FILE_DIR / (root + '-answer.txt')).read_text()
        self.assertEqual(d1.dict, eval(answer))

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True)
        self.assertEqual(d2.dict, eval(answer))

    def test_NHxxLO_xxxx(self):

        self.maxDiff = MAXDIFF

        root = 'lor_0284676508_0x630_sci'
        filepath = TEST_FILE_DIR / (root + '.lbl')
        d1 = Pds3Label(filepath, method='strict', types=True, sources=True)
        answer = (TEST_FILE_DIR / (root + '-answer.txt')).read_text()
        self.assertEqual(d1.dict, eval(answer))

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True)
        self.assertEqual(d2.dict, eval(answer))

    def test_VGISS_xxxx(self):

        self.maxDiff = MAXDIFF

        root = 'C3450702_GEOMED'
        filepath = TEST_FILE_DIR / (root + '.LBL')
        d1 = Pds3Label(filepath, method='strict', types=True, sources=True)
        answer = (TEST_FILE_DIR / (root + '-answer.txt')).read_text()
        self.assertEqual(d1.dict, eval(answer))

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True)
        self.assertEqual(d2.dict, eval(answer))

        d1 = Pds3Label(filepath, method='strict')
        answer = (TEST_FILE_DIR / (root + '-short.txt')).read_text()
        self.assertEqual(d1.dict, eval(answer))

        d2 = Pds3Label(filepath, method='fast')
        self.assertEqual(d2.dict, eval(answer))

        self.assertEqual(len(d1), 61)
        pairs = [('PDS_VERSION_ID', 'PDS3'),
                 ('RECORD_TYPE', 'FIXED_LENGTH'),
                 ('RECORD_BYTES', 2000),
                 ('FILE_RECORDS', 1001),
                 ('^VICAR_HEADER', 'C3450702_GEOMED.IMG'),
                 ('^VICAR_HEADER_offset', 1),
                 ('^VICAR_HEADER_unit', ''),
                 ('^VICAR_HEADER_fmt', '("C3450702_GEOMED.IMG", 1)'),
                 ('^IMAGE', 'C3450702_GEOMED.IMG'),
                 ('^IMAGE_offset', 2),
                 ('^IMAGE_unit', ''),
                 ('^IMAGE_fmt', '("C3450702_GEOMED.IMG", 2)'),
                 ('DATA_SET_ID', 'VG1/VG2-S-ISS-2/3/4/6-PROCESSED-V1.1'),
                 ('PRODUCT_ID', 'C3450702_GEOMED.IMG'),
                 ('PRODUCT_CREATION_TIME', datetime.datetime(2012, 5, 1, 16, 0)),
                 ('PRODUCT_CREATION_TIME_day', 4504),
                 ('PRODUCT_CREATION_TIME_sec', 57600),
                 ('PRODUCT_CREATION_TIME_fmt', '2012-05-01T16:00:00')]
        self.assertEqual(list(d1.items())[:18], pairs)
        self.assertEqual(list(d1.keys())[:18], [p[0] for p in pairs])
        self.assertEqual(list(d1.values())[:18], [p[1] for p in pairs])
        self.assertEqual(d1['PDS_VERSION_ID'], 'PDS3')
        self.assertEqual(d1.get('PDS_VERSION_ID', 'whatever'), 'PDS3')
        self.assertEqual(d1.get('PDS_VERSION_IDx', 'whatever'), 'whatever')
        self.assertTrue('PDS_VERSION_ID' in d1)
        self.assertTrue('PDS_VERSION_IDx' not in d1)

        for test in (str(d1), repr(d1), str(d2), repr(d2)):
            lines = test.split('\n')
            self.assertEqual(lines[:9],
                             ['PDS_VERSION_ID = PDS3',
                              'RECORD_TYPE = FIXED_LENGTH',
                              'RECORD_BYTES = 2000',
                              'FILE_RECORDS = 1001',
                              '^VICAR_HEADER = ("C3450702_GEOMED.IMG", 1)',
                              '^IMAGE = ("C3450702_GEOMED.IMG", 2)',
                              'DATA_SET_ID = "VG1/VG2-S-ISS-2/3/4/6-PROCESSED-V1.1"',
                              'PRODUCT_ID = "C3450702_GEOMED.IMG"',
                              'PRODUCT_CREATION_TIME = 2012-05-01T16:00:00'])

        test = Pds3Label.from_file(str(filepath))
        self.assertEqual(test.dict, d1.dict)

        test = Pds3Label.from_string(d1.content)
        self.assertEqual(test.dict, d1.dict)

        _ = Pds3Label.load_file(FCPath(filepath))
        test = Pds3Label.from_string(d1.content)
        self.assertEqual(test.dict, d1.dict)

        d3 = Pds3Label(filepath, method='strict', _details=True)
        detail = d3['^VICAR_HEADER_detail']
        self.assertEqual(detail.value, d3['^VICAR_HEADER'])
        self.assertEqual(detail.offset, 1)
        self.assertEqual(detail.unit, '')
        self.assertEqual(detail.source, '("C3450702_GEOMED.IMG", 1)')
        self.assertEqual(str(detail), '("C3450702_GEOMED.IMG", 1)')

        detail = d3['EXPOSURE_DURATION_detail']
        self.assertEqual(detail.value, 1.92)
        self.assertEqual(detail.unit, '<SECOND>')
        self.assertEqual(str(detail), '1.92 <SECOND>')

        detail = d3['FILTER_NAME_detail']
        self.assertEqual(detail.value, 'VIOLET')
        self.assertEqual(str(detail), 'VIOLET')

    def test_VG_0xxx(self):

        self.maxDiff = MAXDIFF

        root = 'C3438954'
        filepath = TEST_FILE_DIR / (root + '.IMQ')
        d1 = Pds3Label(filepath, method='loose', types=True, sources=True, expand=False,
                       vax=True)
        answer = (TEST_FILE_DIR / (root + '-answer.txt')).read_text()
        self.assertEqual(d1.dict, eval(answer))

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True, expand=False,
                       vax=True)
        self.assertEqual(d2.dict, eval(answer))

        d1 = Pds3Label(filepath, method='loose', types=True, sources=True, expand=True,
                       vax=True)
        answer = (TEST_FILE_DIR / (root + '-expanded.txt')).read_text()
        self.assertEqual(d1.dict, eval(answer))

        d2 = Pds3Label(filepath, method='fast', types=True, sources=True, expand=True,
                       vax=True)
        self.assertEqual(d2.dict, eval(answer))

    def test_more(self):

        self.maxDiff = MAXDIFF

        root = 'TESTS'
        filepath = TEST_FILE_DIR / (root + '.LBL')
        d1 = Pds3Label(filepath, method='loose', types=True, sources=True)
        answer = (TEST_FILE_DIR / (root + '-answer.txt')).read_text()
        answer_dict = eval(answer)
        self.assertEqual(d1.dict, answer_dict)

        answer_dict['MIXED_SEQ_unit'] = '<km>'
        d2 = Pds3Label(filepath, method='fast', types=True, sources=True)
        self.assertEqual(d2.dict, answer_dict)

    def test_as_dict(self):

        self.maxDiff = MAXDIFF

        root = 'AS_DICT_TEST'
        filepath = TEST_FILE_DIR / (root + '.LBL')
        d1 = Pds3Label(filepath)
        test_dict = d1.as_dict()

        # This is the result of a run of the v1 module...
        old_answer = (TEST_FILE_DIR / (root + '-as_dict.txt')).read_text()
        old_answer_dict = eval(old_answer)

        # new parser does not use "Z" suffix
        test_dict['IMAGE_TIME'] = test_dict['IMAGE_TIME'] + 'Z'

        # a line break in an embedded string is now just a space
        test_dict['SOURCE_PRODUCT_ID'][4] = (test_dict['SOURCE_PRODUCT_ID'][4]
                                             .replace(' ', '\n'))

        # old dicts do not have OBJECT and END_OBJECT entries
        for key in ('IMAGE_HEADER', 'TELEMETRY_TABLE', 'BAD_DATA_VALUES_HEADER', 'IMAGE'):
            del test_dict[key]['OBJECT']
            del test_dict[key]['END_OBJECT']

        # old dicts do not contain END statement
        del test_dict['END']

        self.assertEqual(test_dict, old_answer_dict)


##########################################################################################
