#!/usr/bin/env python3

import argparse
import logging
import os
import os.path
import rx
import rx.subject
import rx.operators
import sys
import threading

from solana.publickey import PublicKey
from solana.rpc.commitment import Max

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
import mango  # nopep8

parser = argparse.ArgumentParser(
    description="Show program logs for an account, as they arrive."
)
mango.ContextBuilder.add_command_line_parameters(parser)
mango.Wallet.add_command_line_parameters(parser)
parser.add_argument(
    "--address",
    type=PublicKey,
    action="append",
    default=[],
    required=True,
    help="Address of the Solana account to watch (can be specified multiple times)",
)
parser.add_argument(
    "--notify",
    type=mango.parse_notification_target,
    action="append",
    default=[],
    help="The notification target for all liquidation events",
)
parser.add_argument(
    "--notify-successful",
    type=mango.parse_notification_target,
    action="append",
    default=[],
    help="The notification target for successful liquidations",
)
parser.add_argument(
    "--notify-failed",
    type=mango.parse_notification_target,
    action="append",
    default=[],
    help="The notification target for failed liquidations",
)
args: argparse.Namespace = mango.parse_args(parser)

with mango.ContextBuilder.from_command_line_parameters(
    args
) as context, mango.Disposable() as disposer:
    context.client.commitment = Max
    mango.output(context)

    manager = mango.IndividualWebSocketSubscriptionManager(context)
    disposer.add_disposable(manager)
    health_check = mango.HealthCheck()
    disposer.add_disposable(health_check)

    publishers = []
    for address in args.address:
        log_subscription = mango.WebSocketLogSubscription(context, address)
        manager.add(log_subscription)
        publishers += [log_subscription.publisher]

    publisher = rx.subject.subject.Subject()
    publisher.pipe(
        rx.operators.merge(*publishers),
        # rx.operators.filter(lambda log_event: "PartialLiquidate" in "\n".join(log_event.logs)),
        # rx.operators.map(mango.debug_print_item("Transaction")),
        # rx.operators.delay(30),  # Wait for the transaction to be fully confirmed
        # rx.operators.map(mango.debug_print_item("After Delay")),
        rx.operators.map(
            lambda log_event: mango.TransactionScout.load(
                context, log_event.signatures[0]
            )
        ),
        rx.operators.filter(lambda item: item is not None),
        rx.operators.catch(mango.observable_pipeline_error_reporter),
        rx.operators.retry(),
    ).subscribe(mango.PrintingObserverSubscriber(False))

    manager.open()

    # Wait - don't exit. Exiting will be handled by signals/interrupts.
    waiter = threading.Event()
    try:
        waiter.wait()
    except:
        pass

    logging.info("Shutting down...")

logging.info("Shutdown complete.")
