"""
This module contains the methods for the ``openxc-trace-split`` command line
program.

`main` is executed when ``openxc-trace-split`` is run, and all other callables
in this module are internal only.
"""


import argparse
import datetime
from operator import itemgetter
from collections import defaultdict

from openxc.formats.json import JsonFormatter
from openxc.sources.trace import TraceDataSource
from .common import configure_logging


class BaseSplitter(object):
    def __init__(self):
        self.records = []
        self.buckets = defaultdict(list)

    def _key_for_record(self, record):
        raise NotImplementedError

    def split(self, files):
        for filename in files:
            source = TraceDataSource(self.receive, filename=filename,
                    loop=False, realtime=False)
            source.start()

        self.records.sort(key=itemgetter('timestamp'))
        for record in self.records:
            self.buckets[self._key_for_record(record)].append(record)

        return self.buckets

    def receive(self, message, **kwargs):
        self.records.append(message)


class TimeSplitter(BaseSplitter):
    def __init__(self, unit):
        super(TimeSplitter, self).__init__()
        self.unit = unit

    def _key_for_record(self, record):
        date = datetime.datetime.fromtimestamp(record['timestamp'])
        if self.unit == "day":
            date_format = '%Y-%m-%d'
        elif self.unit == "hour":
            date_format = '%Y-%m-%d-%H'
        return date.strftime(date_format)


class TripSplitter(BaseSplitter):
    # TODO allow overriding this at the command line
    MAXIMUM_RECORD_GAP_SECONDS = 600

    def _key_for_record(self, record):
        timestamp = record['timestamp']
        last_timestamp = getattr(self, 'last_timestamp', None)
        if last_timestamp is not None:
            if (timestamp - last_timestamp) > self.MAXIMUM_RECORD_GAP_SECONDS:
                self.current_trip_key = timestamp
        else:
            self.current_trip_key = timestamp
        self.last_timestamp = timestamp
        return datetime.datetime.fromtimestamp(self.last_timestamp).strftime(
                "%Y-%m-%d-%H.%M")


def parse_options():
    parser = argparse.ArgumentParser(description="Split a collection of "
            "OpenXC trace files by day, hour or trips")
    parser.add_argument("files", action="store", nargs='+', default=False)
    parser.add_argument("-s", "--split", action="store",
            choices=['day', 'hour', 'trip'], default="trip",
            help="select the time unit to split the combined trace files")

    arguments = parser.parse_args()
    return arguments


def main():
    configure_logging()
    arguments = parse_options()

    if arguments.split == 'trip':
        splitter = TripSplitter()
    else:
        splitter = TimeSplitter(arguments.split)

    for key, split in list(splitter.split(arguments.files).items()):
        with open("%s.json" % key, 'w') as output_file:
            for record in split:
                output_file.write(JsonFormatter.serialize(record) + "\n")
