#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import datetime as dt
import os
import re
import symuid
# import symuid.library.cmus
import sys

FILE_PREFIX = b'CTC'
VERSION_LENGTH = 1
SUPPORTED_VERSION = b'\x0c'
# always big endian, see cache_init()
FLAGS_BYTEORDER = 'big'
FLAGS_LENGTH = 4
FLAG_64_BIT = 0x01
RESERVED_PAD_REGEX = rb'\xff{16,}'
STRING_TERMINATOR = b'\x00'


def _int_from_bytes_sys(data_bytes):
    return int.from_bytes(data_bytes, byteorder=sys.byteorder)


class Track:

    def __init__(self, cache_size, cache_bytes):
        """
        struct cache_entry {
            // size of this struct including size itself
            uint32_t size;
            int32_t play_count;
            int64_t mtime;
            int32_t duration;
            int32_t bitrate;
            int32_t bpm;
            uint8_t _reserved[CACHE_ENTRY_RESERVED_SIZE];
            // filename, codec, codec_profile and N * (key, val)
            char strings[];
        };
        """
        assert len(cache_bytes) + 4 == cache_size
        self._play_count = _int_from_bytes_sys(cache_bytes[0:4])
        # self._mtime = _int_from_bytes_sys(cache_bytes[4:12])
        # self._duration_seconds = _int_from_bytes_sys(cache_bytes[12:16])
        # self._bitrate = _int_from_bytes_sys(cache_bytes[16:20])
        # self._bpm = _int_from_bytes_sys(cache_bytes[20:24])
        strings = re.split(RESERVED_PAD_REGEX, cache_bytes)[1] \
            .split(STRING_TERMINATOR)
        self._path = strings[0]

    @property
    def path(self):
        return self._path

    @property
    def play_count(self):
        return self._play_count


def import_track(cmus_track):
    if cmus_track.play_count > 0:
        print(cmus_track.play_count, cmus_track.path)


def symuid_import_cmus(cache_path):
    with open(os.path.expanduser(cache_path), 'rb') as cache:
        # see cache.c cache_init()
        assert cache.read(len(FILE_PREFIX)) == FILE_PREFIX
        cache_version = cache.read(VERSION_LENGTH)
        assert cache_version == SUPPORTED_VERSION, cache_version
        flags = int.from_bytes(
            cache.read(FLAGS_LENGTH),
            byteorder=FLAGS_BYTEORDER,  # persistent
        )
        assert flags & FLAG_64_BIT
        # support no other flags
        assert flags & ~FLAG_64_BIT == 0, flags
        # size includes size itself
        while True:
            size = _int_from_bytes_sys(cache.read(4))
            if size == 0:
                break
            cmus_track = Track(size, cache.read(size - 4))
            import_track(cmus_track)
            # see cache.c write_ti ALIGN
            cache.read((-size) % 8)


def _init_argparser():
    import argparse
    argparser = argparse.ArgumentParser(description=None)
    argparser.add_argument(
        'cache_path',
        nargs='?',
        default='~/.config/cmus/cache',
        help='(default: %(default)r)',
    )
    return argparser


def main(argv):
    argparser = _init_argparser()
    args = argparser.parse_args(argv[1:])
    symuid_import_cmus(**vars(args))
    return 0

if __name__ == "__main__":
    sys.exit(main(sys.argv))