/*
 */
package com.teltonikaServer.lib;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Americo
 */
public class Protocol {

    public static final byte[] PREAMBLE = {0x00, 0x00, 0x00, 0x00};
    public static final byte[] CODEC12_MESSAGE_ID = {0x0C};
    public static final byte[] CODEC12_COMMAND_ID = {0x05};
    public static final byte[] CODEC12_RESPONSE_ID = {0x06};

    public static final int[] CODEC8_MESSAGE_ID = {0x08};
    
    public static final int IGNITION = 239;
    public static final int MOVEMENT = 240;
    
    public static final int OVERSPEEDING = 11100;
    public static final int SPEED_LIMIT = 11104;
    public static final int SPEED_ALERT = 11103;
    
    public static final int INHIBITOR_ENABLED = 11700;
    public static final int INHIBITOR_OUTPUT = 11702;

    public static byte[] calculateCRC16(byte[] bytes) {
        int crc = CRC16_IBM.getCrc(bytes);
        return get4bytes(crc);
    }

    public static int crc16(final byte[] bytes) {
        int crc = 0xFFFF;

        for (int j = 0; j < bytes.length; j++) {
            crc = ((crc >>> 8) | (crc << 8)) & 0xffff;
            crc ^= (bytes[j] & 0xff);// byte to int, trunc sign
            crc ^= ((crc & 0xff) >> 4);
            crc ^= (crc << 12) & 0xffff;
            crc ^= ((crc & 0xFF) << 5) & 0xffff;
        }/*w ww  .j av a 2  s  .com*/
        crc &= 0xffff;
        return crc;

    }

    public static byte[] get4bytes(String message) {
        return get4bytes(message.length());
    }

    public static byte[] get4bytes(int value) {
        byte byteArray[] = new byte[4];
        byteArray[0] = (byte) ((value >> 24) & 0xFF);
        byteArray[1] = (byte) ((value >> 16) & 0xFF);
        byteArray[2] = (byte) ((value >> 8) & 0xFF);
        byteArray[3] = (byte) (value & 0xFF);

        return byteArray;
    }

    public static byte[] getCommand(String rawCommand) {
        byte binaryCommand[];
        byte commandCount[] = {0x01};

        binaryCommand = Protocol.CODEC12_MESSAGE_ID;
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, commandCount);
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, Protocol.CODEC12_COMMAND_ID);
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, Protocol.get4bytes(rawCommand));
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, rawCommand.getBytes());
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, commandCount);

        int messageLength = binaryCommand.length;
        byte crc16[] = Protocol.calculateCRC16(binaryCommand);

        binaryCommand = Utils.concatenateByteArrays(Utils.concatenateByteArrays(Protocol.PREAMBLE, Protocol.get4bytes(messageLength)), binaryCommand);
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, crc16);

        return binaryCommand;
    }

    public static byte[] getCommand(byte byteArrayCommand[]) {
        byte binaryCommand[];
        byte commandCount[] = {0x01};

        binaryCommand = Protocol.CODEC12_MESSAGE_ID;
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, commandCount);
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, Protocol.CODEC12_COMMAND_ID);
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, Protocol.get4bytes(byteArrayCommand.length));
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, byteArrayCommand);
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, commandCount);

        int messageLength = binaryCommand.length;
        byte crc16[] = Protocol.calculateCRC16(binaryCommand);

        binaryCommand = Utils.concatenateByteArrays(Utils.concatenateByteArrays(Protocol.PREAMBLE, Protocol.get4bytes(messageLength)), binaryCommand);
        binaryCommand = Utils.concatenateByteArrays(binaryCommand, crc16);

        return binaryCommand;
    }
    
    
    public static ImeiCcid getImeiAndCcid(String commandResult) {
        
        //String imei = null;
        //String ccid = null;

        // Definir la expresión regular para extraer IMEI y CCID
        String regex = "IMEI: (\\d+), CCID: (\\d+)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(commandResult);

        ImeiCcid imeiCcid = new ImeiCcid();
        
        // Buscar coincidencias
        if (matcher.find()) {
            imeiCcid.imei = matcher.group(1);
            imeiCcid.ccid = matcher.group(2);
        }

        return imeiCcid;
    }
    
    public static String cleanParameterResponse(String input) {
        String cleanParamString = input.replaceFirst("Param ID:", "").trim();
        cleanParamString = cleanParamString.replaceFirst(" Value","");
        return cleanParamString;
    }
    
    public static List<Map.Entry<Integer, Integer>> parseParams(String input) {
        List<Map.Entry<Integer, Integer>> result = new ArrayList<>();

        // Separar los pares "ID:Valor"
        String[] pairs = input.split(";");

        for (String pair : pairs) {
            // Separar ID y Valor
            String[] keyValue = pair.split(":");
            if (keyValue.length == 2) {
                try {
                    int key = Integer.parseInt(keyValue[0].trim());
                    int value = Integer.parseInt(keyValue[1].trim());
                    result.add(new AbstractMap.SimpleEntry<>(key, value));
                } catch (NumberFormatException e) {
                    System.err.println("Error al parsear: " + pair);
                }
            }
        }

        return result;
    }
}


