#!/usr/bin/env python3
#
# Copyright 2021-2022 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
#
# Partially decode gpsOne xtra files.
#
# Credit:
# Vinnikov & Pshehotskaya (2020):
# Deciphering of the gpsOne File Format for Assisted GPS Service,
# Advances in Intelligent Systems and Computing 1184:377-386
# https://www.researchgate.net/publication/338712609_Deciphering_of_the_gpsOne_File_Format_for_Assisted_GPS_Service

import os
import struct
import sys

from util import datetime_from_gpstime


class Xtra(object):

    def __init__(self, filename, fix_week=False):
        with open(filename, 'rb') as ff:
            bb = ff.read(80)
            ff.seek(0, os.SEEK_END)
            self.file_len = ff.tell()

        self.header = bb

        header, fmt_ver = struct.unpack('BB', bb[:2])
        self.version = None
        if header != 1:
            raise ValueError("Header 1st byte mismatch")
        self.version = "Unknown"
        if fmt_ver == 0x1b:
            self.version = "1"
        elif fmt_ver == 0x34:
            self.version = "2 or 3"

        self.length, = struct.unpack('>I', bb[0x0b:0x0f])

        self.actual_dt = datetime_from_gpstime(
            *struct.unpack('>HI', bb[0x0f:0x15]),
            fix_week=fix_week)
        self.reference_dt = datetime_from_gpstime(
            *struct.unpack('>HI', bb[0x15:0x1b]),
            fix_week=fix_week)

        self.fixed_actual_dt = datetime_from_gpstime(
            *struct.unpack('>HI', bb[0x0f:0x15]),
            fix_week=True)
        self.fixed_reference_dt = datetime_from_gpstime(
            *struct.unpack('>HI', bb[0x15:0x1b]),
            fix_week=True)


if __name__ == '__main__':
    infile = sys.argv[1]
    x = Xtra(infile)
    print(f"Filename: {infile}")
    print(f"File len: {x.file_len}")
    print(f"Lenght in file: {x.length}")
    print(f"Version: {x.version}")
    print(f"Actual time:    {x.actual_dt}")
    print(f"Reference time: {x.reference_dt}")
    print(f"Week-fixed Reference time: {x.fixed_reference_dt}")
    print(f"Week-fixed Actual time:    {x.fixed_actual_dt}")
