/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cloudsoft.MastercardFileReader;

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.google.gson.Gson;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
/**
 *
 * @author paul
 */
public class Main {
    private final static String QUEUE_NAME = "iso8583";
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        IPMInputStream is = new IPMInputStream("c:/dev/T112.500K.ipm");
//        IPMInputStream is = new IPMInputStream("c:/dev/SimpleSmallFile.ipm");

//        var blockSize = 1012;
//        var blockChar = 0x00;
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        while (!is.lastBlock()) {
            byte[] ba = is.readNBytes(4);
//            System.out.println(Integer.toBinaryString(ba[0]));
//            System.out.println(Integer.toBinaryString(ba[1]));
//        System.out.println(String.format("%8s", Integer.toBinaryString(ba[2])).replace(' ', '0'));
//        System.out.println(String.format("%8s", Integer.toBinaryString(ba[3])).replace(' ', '0'));
//        System.out.println(Integer.toBinaryString(ba[3] & 0xFF));
//        System.out.println(new String(ba, "Windows-1252"));
            // format is 00LL bytes 0 and 1 should be 0
            int recordLength = 256 * (ba[2] & 0xFF) + (ba[3] & 0xFF);
            if (recordLength == 0) {
                System.exit(0);
            }
//            System.out.println(recordLength);
            //ba = bais.readNBytes(recordLength);
//            ByteArrayInputStream bais = new ByteArrayInputStream(ba);
            Boolean[] RecordBitmap = new Boolean[IpmSpecificationConstants.DataElementCount];
            String[] RecordDataElements = new String[IpmSpecificationConstants.DataElementCount];
            RecordBitmap[0] = true;

            byte[] messageTypeIdBytes = is.readNBytes(4);
            String messsageTypeId = new String(messageTypeIdBytes, "Windows-1252");
//            System.out.format("Message Type : %s\n", messsageTypeId);
            for (int i = 0; i < IpmSpecificationConstants.DataElementCount; i++) {
                if (RecordBitmap[i]) {
                    StringBuilder sb = new StringBuilder();
                    int elementLength = GetDataElementLength(is, i);
                    ba = is.readNBytes(elementLength);
                    IpmSpecificationConstants.DataElementFormat elementFormat = IpmDataElements.DataElements[i].Format;
                    if (elementFormat == IpmSpecificationConstants.DataElementFormat.Binary) {
                        for (int j = 0; j < elementLength; j++) {
                            sb.append(String.format("%8s", Integer.toBinaryString(ba[j] & 0xFF)).replace(' ', '0'));
                        }
                        String binaryStringValue = sb.toString();
                        boolean isBitmap = IpmDataElements.DataElements[i].IsBitmap;
                        if (isBitmap) {
                            int bitmapStartIndex = IpmDataElements.DataElements[i].BitmapStartIndex;
                            for (int j = 0; j < binaryStringValue.length(); j++) {
                                char c = binaryStringValue.charAt(j);
                                RecordBitmap[j + bitmapStartIndex] = c == '1';
                            }
                        }
                        RecordDataElements[i] = sb.toString();
                    } else if (elementFormat == IpmSpecificationConstants.DataElementFormat.HexadecimalBinary) {
                        RecordDataElements[i] = new BigInteger(ba).toString(16);
                    } else {
                        RecordDataElements[i] = new String(ba, "Windows-1252");
                    }
                }
            }
            // We have a whole messasge
            Gson gson = new Gson();
            ArrayList<IsoElement> elements = new ArrayList<IsoElement>();
            for (int i = 0; i < RecordDataElements.length; i++) {
                if (RecordBitmap[i]) {
                    elements.add(new IsoElement(i, IpmDataElements.DataElements[i].Name, RecordDataElements[i]));
//                    System.out.format("%03d (%s): %s\n", i, IpmDataElements.DataElements[i].Name, RecordDataElements[i]);
                }
            }
            String message = gson.toJson(elements);
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
        }
    }

    static int GetDataElementLength(IPMInputStream bais, int dataElementIndex) {
        int elementSize = IpmDataElements.DataElements[dataElementIndex].LengthData.LllSize;
        if (elementSize == 0) {
            return IpmDataElements.DataElements[dataElementIndex].LengthData.MaximumLength;
        }
        String s = "";
        try {
            byte[] elementLengthBytes = bais.readNBytes(elementSize);
            s = new String(elementLengthBytes);
            return Integer.parseInt(s);
        } catch (Exception ex) {
            System.out.format("%03d: %s is not a number\n", dataElementIndex, s);
            return 4;
        }
    }
    
}
