#!/usr/bin/python3

import string
import json
import csv
import logging
import argparse
import subprocess
import sys
import collections

logging.basicConfig(
         format='%(asctime)s %(levelname)-8s %(message)s',
         level=logging.INFO,
         filename='current_validators.log',
         datefmt='%Y-%m-%d %H:%M:%S')


def parseTransactions(ledger):

    logging.info("Parsing ledger transactions into dictionary")

    validators = collections.OrderedDict()
    # validators is dictionary of dictionaries that maps dest to the current values of the attritubes for that dest
    #  { dest1:{'alias':value1, 'blskey':value1, ...} , dest2:{'alias':value2, 'blskey':value2, ...}, ...}

    for lLine in ledger:
        txn_json_dump = json.loads(lLine)

        if (txn_json_dump[1]['dest'] is None ) :
            break
        else:
            # Get destination field from the JSON dump of the current transaction
            current_dest = txn_json_dump[1]['dest']

            data_json_dump = txn_json_dump[1]['data']

            # Add destination to the dictionary if it does not exist
            if not( current_dest in validators.keys() ):
                validators[ current_dest ] = {}

            # Update attribute value of the destination if the attributes exists in the current transaction dump
            try:
                validators[current_dest]['alias']  = data_json_dump['alias']
            except KeyError:
                pass
            try:
                validators[current_dest]['blskey']  = data_json_dump['blskey']
            except KeyError:
                pass
            try:
                validators[current_dest]['client_ip']  = data_json_dump['client_ip']
            except KeyError:
                pass
            try:
                validators[current_dest]['client_port']  = data_json_dump['client_port']
            except KeyError:
                pass
            try:
                validators[current_dest]['node_ip']  = data_json_dump['node_ip']
            except KeyError:
                pass
            try:
                validators[current_dest]['node_port']  = data_json_dump['node_port']
            except KeyError:
                pass
            try:
                validators[current_dest]['services']  = data_json_dump['services']
            except KeyError:
                pass
            if 'identifier' not in validators[current_dest]:
                try:
                    validators[current_dest]['identifier']  = txn_json_dump[1]['identifier']
                except KeyError:
                    pass
            validators[current_dest]['dest']  = current_dest

    return validators


def getLedger():
    try:
        completed = subprocess.run(
        ['sudo', '/usr/local/bin/read_ledger', '--type', 'pool', '--count'],
        check=True,
        stdout=subprocess.PIPE,
        )
    except subprocess.CalledProcessError as err:
        logger.error('ERROR attempting to run read_ledger --count subprocess: {}'.format(err))
        raise
    transCount = completed.stdout.decode('utf-8').strip()
    logging.info("{} entries in ledger.".format(transCount))
    try:
        completed = subprocess.run(
        ['sudo', '/usr/local/bin/read_ledger', '--type', 'pool', '--frm', '1', '--to', completed.stdout],
        check=True,
        stdout=subprocess.PIPE,
        )
    except subprocess.CalledProcessError as err:
        logger.error('ERROR attempting to run read_ledger subprocess to capture ledger data: {}'.format(err))
        raise

    ledgerLines = completed.stdout.decode('utf-8').splitlines()
    logging.info("{} ledger entries received.".format(len(ledgerLines)))
    return ledgerLines

def writeResult(jsonOut):

    if jsonOut:
        logging.info("Serializing info on validators to json")
        count = len(validators)
        print('[', end='')
        for i in validators.keys():
            print(json.dumps(validators[i], sort_keys=True), end='')
            if count > 1:
                print(',', end='')
                count -= 1
        print(']')
    else:
        logging.info("Serializing info on validators to csv")
        fieldnames = ['alias', 'blskey', 'client_ip', 'client_port', 'node_ip', 'node_port', 'services', 'dest', 'identifier']
        writer = csv.DictWriter(sys.stdout, fieldnames=fieldnames)
        writer.writeheader()
        for i in validators.keys():
            writer.writerow(validators[i])

def parseInputs():
    parser = argparse.ArgumentParser(description = 'This script may be run on a validator node to discover information on all the validators configured in the ledger.')
    parser.add_argument('--writeJson', help='Boolean flag.  If set, the output is json. (Default: the output is csv.)', action='store_true')
    args = parser.parse_args()
    return args.writeJson


if __name__ == '__main__':
    writeJson = parseInputs()
    ledger = getLedger()
    validators = parseTransactions(ledger)
    writeResult = writeResult(writeJson)