import json

class Parser:
    '''
    An object to parse the main log files generated by TransEquilibrium.

    The log file is a sequence of JSON objects, but it's not a JSON object itself.
    This is because we want to just open the file, dump some log and close it. We
    don't want to have to delete to reparse it every time to correctly log.

    This object also allow to select which type of objects to retrive. For instance,
    you can only get retweets.
    '''

    def __init__(self, log_file_path, tweets=None, retweets=None, following=None):
        '''
        Initialize a Parser instance.

        If `tweets`, `retweets` and `following` are ALL unset, then all the elements are
        returned.

        If any of `tweets`, `retweets` or `following` are set, then only tweets matching
        the specified types are returned.

        This mean the you can just do `for item in Parser(path)` to iterate everything
        or specify only a subset of types, like in `for item in Parser(path, tweets=True)`.

        log_file_path:
            A path to a log file to parse.
        tweets:
            Whether to return normal tweets (including ones with quoted text).
        retweets:
            Whether to return retweets.
        following:
            Whether to return new followed accounts.
        '''

        if tweets is None and retweets is None and following is None:
            tweets = True
            retweets = True
            following = True
        else:
            tweets = False if tweets is None else tweets
            retweets = False if retweets is None else retweets
            following = False if following is None else following

        self._tweets = bool(tweets)
        self._retweets = bool(retweets)
        self._following = bool(following)

        self._log_file = open(log_file_path)

    def __del__(self):
        self._log_file.close()

    @staticmethod
    def _get_object_type(json_object):
        if 'skipped-because-retweet' in json_object:
            return 'retweet'
        elif 'following-id' in json_object:
            return 'following'
        elif 'translated-text' in json_object:
            return 'tweet'
        else:
            raise ValueError('Invalid object: {}'.format(json_object))

    def _should_skip(self, json_object):
        conditions = {
            'tweet': self._tweets,
            'retweet': self._retweets,
            'following': self._following,
            }
        return not conditions[self._get_object_type(json_object)]

    def __iter__(self):
        iterator = iter(self._log_file)

        for line_ext in iterator:
            line_ext = line_ext.rstrip()
            assert line_ext == '{'
            content_list = [line_ext]

            for line_int in iterator:
                line_int = line_int.rstrip()
                content_list.append(line_int)
                if line_int == '}':
                    break

            content = '\n'.join(content_list)
            json_object = json.loads(content)

            if self._should_skip(json_object):
                continue

            yield json_object

    def __reversed__(self):
        # This is fast enough.
        return reversed(list(self))
