// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.impl.google.lib.discovery;


import com.google.common.primitives.Bytes;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import io.v.v23.vom.BinaryUtil;
import io.v.x.ref.lib.discovery.EncryptionKey;

/**
 * A utility to encode and decode fields in io.v.v23.Service fields for use in discovery.
 */
public class EncodingUtil {
    static final Charset UTF8_CHARSET = Charset.forName("UTF-8");

    /**
     * Encodes the addresses passed in.
     * @param addrs The list of addresses to encode.
     * @return The byte representation of the encoded addresses.
     * @throws IOException
     */
    public static byte[] packAddresses(List<String> addrs) throws IOException {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        for (String addr : addrs) {
            BinaryUtil.encodeUint(stream, addr.length());
            stream.write(addr.getBytes(UTF8_CHARSET));
        }
        return stream.toByteArray();
    }

    /**
     * Decodes addresses from a byte array that was encoded by packAddresses
     * @param input The byte array toe decode
     * @return The list of addresses.
     * @throws IOException
     */
    public static List<String> unpackAddresses(byte[] input) throws IOException {
        ByteArrayInputStream stream = new ByteArrayInputStream(input);
        List<String> output = new ArrayList<>();
        while (stream.available() > 0) {
            int stringSize = (int)BinaryUtil.decodeUint(stream);
            byte[] data = new byte[stringSize];
            int read = stream.read(data);
            if (read != stringSize) {
                throw new IOException("Unexpected end of stream while reading address");
            }
            output.add(new String(data, UTF8_CHARSET));
        }
        return output;
    }

    /**
     * Encode the encryption keys and algorithm passed in.
     * @param encryptionAlgorithm The encryption algorithm to use.
     *                            See io.v.x.ref.lib.discovery.Constants for valid values.
     * @param keys The keys to encode
     * @return The byte array that is the encoded form.
     * @throws IOException
     */
    public static byte[] packEncryptionKeys(int encryptionAlgorithm, List<EncryptionKey> keys)
            throws IOException {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        BinaryUtil.encodeUint(stream, encryptionAlgorithm);
        for (EncryptionKey key : keys) {
            byte[] byteKey = Bytes.toArray(key);
            BinaryUtil.encodeUint(stream, byteKey.length);
            stream.write(byteKey);
        }
        return stream.toByteArray();
    }


    /**
     * Decodes the encryption algorithm and keys that was encoded by packEncryptionKeys.
     * @param input The byte array containg the keys.
     * @return The keys and the encryption algorithm in input.
     * @throws IOException
     */
    public static KeysAndAlgorithm unpackEncryptionKeys(byte[] input) throws IOException {
        ByteArrayInputStream stream = new ByteArrayInputStream(input);
        int algo = (int) BinaryUtil.decodeUint(stream);
        List<EncryptionKey> keys = new ArrayList<>();
        while (stream.available() > 0) {
            int size = (int) BinaryUtil.decodeUint(stream);
            byte[] key = new byte[size];
            int read = stream.read(key);
            if (read != size) {
                throw new IOException("Unexpected end of file reading keys");
            }
            keys.add(new EncryptionKey(Bytes.asList(key)));
        }
        return new KeysAndAlgorithm(algo, keys);
    }

    /**
     * An object with EncryptionKeys and the encryption algorithm.
     */
    public static class KeysAndAlgorithm {
        int encryptionAlgorithm;
        List<EncryptionKey> keys;

        /**
         * Gets the stored encryption algorithm.
         */
        public int getEncryptionAlgorithm() {
            return encryptionAlgorithm;
        }

        /**
         * Gets the stored keys.
         */
        public List<EncryptionKey> getKeys() {
            return keys;
        }

        KeysAndAlgorithm(int encryptionAlgo, List<EncryptionKey> keys) {
            encryptionAlgorithm = encryptionAlgo;
            this.keys = keys;
        }
    }

}
