# Path: beancount_import/journal_editor.py
# META_IGNORE = get_meta_ignore()
# 
# Path: beancount_import/sorted_list.py
# class SortedList(Generic[K, V]):
#     def __init__(self, items: Iterable[Tuple[K, V]]) -> None:
#         entries = sorted(items, key=lambda x: x[0])
#         self.keys = [x[0] for x in entries]
#         self.values = [x[1] for x in entries]
# 
#     def __repr__(self) -> str:
#         return repr(list(zip(self.keys, self.values)))
# 
#     def find(self, lower_bound: K, upper_bound: K) -> Iterable[V]:
#         keys = self.keys
#         begin_pos = bisect.bisect_left(keys, lower_bound)
#         end_pos = bisect.bisect_right(keys, upper_bound)
#         if begin_pos == end_pos:
#             return ()
#         return itertools.islice(self.values, begin_pos, end_pos)
# 
# Path: beancount_import/posting_date.py
# def get_posting_date(entry, posting):
#     """Returns the date associated with a posting."""
#     return ((posting.meta and (posting.meta.get(POSTING_DATE_KEY) or
#                                posting.meta.get(POSTING_TRANSACTION_DATE_KEY))) or entry.date)
# 
# POSTING_DATE_KEY = 'date'
# 
# POSTING_TRANSACTION_DATE_KEY = 'transaction_date'


import datetime
import collections
import itertools
import beancount.parser.printer
from typing import Sequence, Tuple, List, NamedTuple, Dict, Callable, Optional, Iterable, Set, cast, FrozenSet, Union, Any
from beancount.core.number import MISSING, ZERO, Decimal
from beancount.core.data import Transaction, Posting, Meta, Cost, CostSpec
from beancount.core.amount import mul as amount_mul
from beancount.core.amount import Amount
from beancount.parser import booking_full
from .journal_editor import META_IGNORE
from .sorted_list import SortedList
from .posting_date import get_posting_date, POSTING_DATE_KEY, POSTING_TRANSACTION_DATE_KEY
                        MatchGroupKey(currency, is_positive), [])
                    for txn_matchable_posting_groups in matchable_posting_groups)
                for is_positive in (False, True)))
        match_groups[currency] = compute_balanced_match_group(
            matchable_postings,
            unweighted_postings,
            max_residual=max_residuals.get(currency, ZERO),
            is_cleared=is_cleared)

    postings_matched = set()  # type: Set[int]

    for match_sets in itertools.product(*match_groups.values()):
        combined_matches = sum((match_set.matches for match_set in match_sets),
                               [])  # type: PostingMatches
        combined_removals = sum((match_set.removals
                                 for match_set in match_sets), ())
        if not combined_matches:
            continue
        for m in combined_matches:
            postings_matched.update(get_posting_ids_in_match(m))
        results.append(
            combine_transactions_using_match_set(
                txns,
                is_cleared=is_cleared,
                match_set=PostingMatchSet(combined_matches, combined_removals)))
    return results, postings_matched


def get_posting_identifier(posting: Posting) -> Posting:
    if posting.meta:

# Path: beancount_import/journal_editor.py
# META_IGNORE = get_meta_ignore()
# 
# Path: beancount_import/sorted_list.py
# class SortedList(Generic[K, V]):
#     def __init__(self, items: Iterable[Tuple[K, V]]) -> None:
#         entries = sorted(items, key=lambda x: x[0])
#         self.keys = [x[0] for x in entries]
#         self.values = [x[1] for x in entries]
# 
#     def __repr__(self) -> str:
#         return repr(list(zip(self.keys, self.values)))
# 
#     def find(self, lower_bound: K, upper_bound: K) -> Iterable[V]:
#         keys = self.keys
#         begin_pos = bisect.bisect_left(keys, lower_bound)
#         end_pos = bisect.bisect_right(keys, upper_bound)
#         if begin_pos == end_pos:
#             return ()
#         return itertools.islice(self.values, begin_pos, end_pos)
# 
# Path: beancount_import/posting_date.py
# def get_posting_date(entry, posting):
#     """Returns the date associated with a posting."""
#     return ((posting.meta and (posting.meta.get(POSTING_DATE_KEY) or
#                                posting.meta.get(POSTING_TRANSACTION_DATE_KEY))) or entry.date)
# 
# POSTING_DATE_KEY = 'date'
# 
# POSTING_TRANSACTION_DATE_KEY = 'transaction_date'


# Path: beancount_import/matching.py
import datetime
import collections
import itertools
import beancount.parser.printer
from typing import Sequence, Tuple, List, NamedTuple, Dict, Callable, Optional, Iterable, Set, cast, FrozenSet, Union, Any
from beancount.core.number import MISSING, ZERO, Decimal
from beancount.core.data import Transaction, Posting, Meta, Cost, CostSpec
from beancount.core.amount import mul as amount_mul
from beancount.core.amount import Amount
from beancount.parser import booking_full
from .journal_editor import META_IGNORE
from .sorted_list import SortedList
from .posting_date import get_posting_date, POSTING_DATE_KEY, POSTING_TRANSACTION_DATE_KEY

                        MatchGroupKey(currency, is_positive), [])
                    for txn_matchable_posting_groups in matchable_posting_groups)
                for is_positive in (False, True)))
        match_groups[currency] = compute_balanced_match_group(
            matchable_postings,
            unweighted_postings,
            max_residual=max_residuals.get(currency, ZERO),
            is_cleared=is_cleared)

    postings_matched = set()  # type: Set[int]

    for match_sets in itertools.product(*match_groups.values()):
        combined_matches = sum((match_set.matches for match_set in match_sets),
                               [])  # type: PostingMatches
        combined_removals = sum((match_set.removals
                                 for match_set in match_sets), ())
        if not combined_matches:
            continue
        for m in combined_matches:
            postings_matched.update(get_posting_ids_in_match(m))
        results.append(
            combine_transactions_using_match_set(
                txns,
                is_cleared=is_cleared,
                match_set=PostingMatchSet(combined_matches, combined_removals)))
    return results, postings_matched


def get_posting_identifier(posting: Posting) -> Posting:
    if posting.meta:

        meta = [(k, v) for k, v in posting.meta.items() if k not in META_IGNORE]