package android.view;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * {@link ViewHierarchyEncoder} is a serializer that is tailored towards writing out
 * view hierarchies (the view tree, along with the properties for each view) to a stream.
 *
 * It is typically used as follows:
 * <pre>
 *   ViewHierarchyEncoder e = new ViewHierarchyEncoder();
 *
 *   for (View view : views) {
 *      e.beginObject(view);
 *      e.addProperty("prop1", value);
 *      ...
 *      e.endObject();
 *   }
 *
 *   // repeat above snippet for each view, finally end with:
 *   e.endStream();
 * </pre>
 *
 * <p>On the stream, a snippet such as the above gets encoded as a series of Map's (one
 * corresponding to each view) with the property name as the key and the property value
 * as the value.
 *
 * <p>Since the property names are practically the same across all views, rather than using
 * the property name directly as the key, we use a short integer id corresponding to each
 * property name as the key. A final map is added at the end which contains the mapping
 * from the integer to its property name.
 *
 * <p>A value is encoded as a single byte type identifier followed by the encoding of the
 * value. Only primitive types are supported as values, in addition to the Map type.
 *
 * @hide
 */
public class ViewHierarchyEncoder {
    // Prefixes for simple primitives. These match the JNI definitions.
    private static final byte SIG_BOOLEAN = 'Z';
    private static final byte SIG_BYTE = 'B';
    private static final byte SIG_SHORT = 'S';
    private static final byte SIG_INT = 'I';
    private static final byte SIG_LONG = 'J';
    private static final byte SIG_FLOAT = 'F';
    private static final byte SIG_DOUBLE = 'D';

    // Prefixes for some commonly used objects
    private static final byte SIG_STRING = 'R';

    private static final byte SIG_MAP = 'M'; // a map with an short key
    private static final short SIG_END_MAP = 0;

    private final DataOutputStream mStream;

    private final Map<String,Short> mPropertyNames = new HashMap<String, Short>(200);
    private short mPropertyId = 1;
    private Charset mCharset = Charset.forName("utf-8");

    private boolean mUserPropertiesEnabled = true;

    public ViewHierarchyEncoder(@NonNull ByteArrayOutputStream stream) {
        mStream = new DataOutputStream(stream);
    }

    public void setUserPropertiesEnabled(boolean enabled) {
        mUserPropertiesEnabled = enabled;
    }

    public void beginObject(@NonNull Object o) {
        startPropertyMap();
        addProperty("meta:__name__", o.getClass().getName());
        addProperty("meta:__hash__", o.hashCode());
    }

    public void endObject() {
        endPropertyMap();
    }

    public void endStream() {
        // write out the string table
        startPropertyMap();
        addProperty("__name__", "propertyIndex");
        for (Map.Entry<String,Short> entry : mPropertyNames.entrySet()) {
            writeShort(entry.getValue());
            writeString(entry.getKey());
        }
        endPropertyMap();
    }

    @UnsupportedAppUsage
    public void addProperty(@NonNull String name, boolean v) {
        writeShort(createPropertyIndex(name));
        writeBoolean(v);
    }

    public void addProperty(@NonNull String name, short s) {
        writeShort(createPropertyIndex(name));
        writeShort(s);
    }

    @UnsupportedAppUsage
    public void addProperty(@NonNull String name, int v) {
        writeShort(createPropertyIndex(name));
        writeInt(v);
    }

    @UnsupportedAppUsage
    public void addProperty(@NonNull String name, float v) {
        writeShort(createPropertyIndex(name));
        writeFloat(v);
    }

    @UnsupportedAppUsage
    public void addProperty(@NonNull String name, @Nullable String s) {
        writeShort(createPropertyIndex(name));
        writeString(s);
    }

    /**
     * Encodes a user defined property if they are allowed to be encoded
     *
     * @see #setUserPropertiesEnabled(boolean)
     */
    public void addUserProperty(@NonNull String name, @Nullable String s) {
        if (mUserPropertiesEnabled) {
            addProperty(name, s);
        }
    }

    /**
     * Writes the given name as the property name, and leaves it to the callee
     * to fill in value for this property.
     */
    public void addPropertyKey(@NonNull String name) {
        writeShort(createPropertyIndex(name));
    }

    private short createPropertyIndex(@NonNull String name) {
        Short index = mPropertyNames.get(name);
        if (index == null) {
            index = mPropertyId++;
            mPropertyNames.put(name, index);
        }

        return index;
    }

    private void startPropertyMap() {
        try {
            mStream.write(SIG_MAP);
        } catch (IOException e) {
            // does not happen since the stream simply wraps a ByteArrayOutputStream
        }
    }

    private void endPropertyMap() {
        writeShort(SIG_END_MAP);
    }

    private void writeBoolean(boolean v) {
        try {
            mStream.write(SIG_BOOLEAN);
            mStream.write(v ? 1 : 0);
        } catch (IOException e) {
            // does not happen since the stream simply wraps a ByteArrayOutputStream
        }
    }

    private void writeShort(short s) {
        try {
            mStream.write(SIG_SHORT);
            mStream.writeShort(s);
        } catch (IOException e) {
            // does not happen since the stream simply wraps a ByteArrayOutputStream
        }
    }

    private void writeInt(int i) {
        try {
            mStream.write(SIG_INT);
            mStream.writeInt(i);
        } catch (IOException e) {
            // does not happen since the stream simply wraps a ByteArrayOutputStream
        }
    }

    private void writeFloat(float v) {
        try {
            mStream.write(SIG_FLOAT);
            mStream.writeFloat(v);
        } catch (IOException e) {
            // does not happen since the stream simply wraps a ByteArrayOutputStream
        }
    }

    private void writeString(@Nullable String s) {
        if (s == null) {
            s = "";
        }

        try {
            mStream.write(SIG_STRING);
            byte[] bytes = s.getBytes(mCharset);

            short len = (short)Math.min(bytes.length, Short.MAX_VALUE);
            mStream.writeShort(len);

            mStream.write(bytes, 0, len);
        } catch (IOException e) {
            // does not happen since the stream simply wraps a ByteArrayOutputStream
        }
    }
}
