package {{ root_package }}.extensions.{{ extension }}.types;

import {{ root_package }}.internal.JsonSupport;
import {{ root_package }}.internal.WireSerializable;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public final class Vector implements WireSerializable {
    private final List<Float> value;

    public Vector(List<Float> value) {
        this.value = value == null ? List.of() : List.copyOf(value);
    }

    public static Vector of(List<Float> value) {
        return new Vector(value);
    }

    public static Vector of(float... values) {
        ArrayList<Float> items = new ArrayList<>();
        if (values != null) {
            for (float value : values) {
                items.add(value);
            }
        }
        return new Vector(items);
    }

    public static Vector of(double... values) {
        ArrayList<Float> items = new ArrayList<>();
        if (values != null) {
            for (double value : values) {
                items.add((float) value);
            }
        }
        return new Vector(items);
    }

    public static Vector empty() {
        return new Vector(List.of());
    }

    public static Vector fromJsonNode(JsonNode node) {
        List<Float> value = JsonSupport.asFloatList(node);
        return value == null ? null : new Vector(value);
    }

    public List<Float> value() {
        return this.value;
    }

    public List<Float> toList() {
        return this.value;
    }

    public Float get(int index) {
        return this.value.get(index);
    }

    public int size() {
        return this.value.size();
    }

    public boolean isEmpty() {
        return this.value.isEmpty();
    }

    public Vector concat(Iterable<? extends Number> other) {
        ArrayList<Float> next = new ArrayList<>(this.value);
        if (other != null) {
            for (Number item : other) {
                next.add(item.floatValue());
            }
        }
        return new Vector(next);
    }

    public List<Float> toWire() {
        return this.value;
    }

    public boolean equals(List<Float> other) {
        return Objects.equals(this.value, other);
    }

    @Override
    public JsonNode toJsonNode() {
        return JsonSupport.toJsonNode(this.value);
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (other instanceof Vector typed) {
            return Objects.equals(this.value, typed.value);
        }
        if (other instanceof List<?> raw) {
            return Objects.equals(this.value, raw);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(this.value);
    }

    @Override
    public String toString() {
        return this.value.toString();
    }
}
