package com.lanyuanxiaoyao.service.configuration.entity.queue;

import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * 队列对象
 *
 * @author lanyuanxiaoyao
 * @date 2023-05-06
 */
public final class QueueItem<E> implements Comparable<QueueItem<E>> {
    private final String traceId;
    private final Long createTime;

    private String id;
    private Map<String, String> metadata;
    private Integer priority;
    private E data;

    public QueueItem() {
        this.traceId = UUID.randomUUID().toString();
        this.createTime = Instant.now().toEpochMilli();
    }

    public QueueItem(String id) {
        this();
        this.id = id;
    }

    public QueueItem(String id, Integer priority) {
        this(id);
        this.priority = priority;
    }

    public QueueItem(String id, Integer priority, E data) {
        this(id, priority);
        this.data = data;
    }

    public QueueItem(String id, Map<String, String> metadata, Integer priority, E data) {
        this(id, priority, data);
        this.metadata = metadata;
    }

    public String getTraceId() {
        return traceId;
    }

    public Long getCreateTime() {
        return createTime;
    }

    public String getId() {
        return id;
    }

    public Map<String, String> getMetadata() {
        return metadata == null ? new HashMap<>() : metadata;
    }

    public String getMetadata(String key) {
        return metadata == null ? null : metadata.get(key);
    }

    public String getMetadata(String key, String defaultValue) {
        return metadata == null ? defaultValue : metadata.getOrDefault(key, defaultValue);
    }

    public void setMetadata(String key, String value) {
        if (metadata == null) {
            metadata = new HashMap<>();
        }
        metadata.put(key, value);
    }

    public Integer getPriority() {
        return priority;
    }

    public E getData() {
        return data;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        QueueItem<?> queueItem = (QueueItem<?>) o;

        return id.equals(queueItem.id);
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }

    @Override
    public String toString() {
        return "QueueItem{" +
                "traceId='" + traceId + '\'' +
                ", createTime=" + createTime +
                ", id='" + id + '\'' +
                ", metadata=" + metadata +
                ", priority=" + priority +
                ", data=" + data +
                '}';
    }

    @Override
    public int compareTo(QueueItem<E> o) {
        Integer p1 = this.priority;
        Integer p2 = o.priority;
        if (Objects.equals(p1, p2)) {
            return 0;
        } else if (p1 == null) {
            return 1;
        } else if (p2 == null) {
            return -1;
        } else {
            return Integer.compare(p2, p1);
        }
    }
}
