package com.lanyuanxiaoyao.service.web.entity;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.lanyuanxiaoyao.service.configuration.entity.flink.FlinkCheckpoint;
import com.lanyuanxiaoyao.service.configuration.entity.flink.FlinkVertex;
import org.eclipse.collections.api.list.ImmutableList;

/**
 * @author lanyuanxiaoyao
 * @date 2023-05-05
 */
public final class FlinkVertexVO {
    @JsonIgnore
    private final FlinkVertex vertex;

    private final ImmutableList<FlinkCheckpoint> checkpoints;
    private final CheckpointMetrics checkpointMetrics;
    private final String page;
    private final ImmutableList<FlinkVertexChildVO> children;
    private Metrics metrics;

    public FlinkVertexVO(FlinkVertex vertex, String page, ImmutableList<FlinkVertexChildVO> children, ImmutableList<FlinkCheckpoint> checkpoints) {
        this.vertex = vertex;
        this.page = page;

        this.children = children;
        if (ObjectUtil.isNotNull(children)) {
            this.metrics = new Metrics(
                    children
                            .reject(ObjectUtil::isNull)
                            .reject(v -> ObjectUtil.isNull(v.getMetrics()))
                            .reject(v -> ObjectUtil.isNull(v.getMetrics().getReadBytes()))
                            .sumOfLong(v -> v.getMetrics().getReadBytes()),
                    children
                            .reject(ObjectUtil::isNull)
                            .reject(v -> ObjectUtil.isNull(v.getMetrics()))
                            .reject(v -> ObjectUtil.isNull(v.getMetrics().getReadRecords()))
                            .sumOfLong(v -> v.getMetrics().getReadRecords()),
                    children
                            .reject(ObjectUtil::isNull)
                            .reject(v -> ObjectUtil.isNull(v.getMetrics()))
                            .reject(v -> ObjectUtil.isNull(v.getMetrics().getWriteBytes()))
                            .sumOfLong(v -> v.getMetrics().getWriteBytes()),
                    children
                            .reject(ObjectUtil::isNull)
                            .reject(v -> ObjectUtil.isNull(v.getMetrics()))
                            .reject(v -> ObjectUtil.isNull(v.getMetrics().getWriteRecords()))
                            .sumOfLong(v -> v.getMetrics().getWriteRecords())
            );
        }
        this.checkpoints = checkpoints;
        this.checkpointMetrics = new CheckpointMetrics(
                checkpoints.count(c -> StrUtil.equals("COMPLETED", c.getStatus())),
                checkpoints.count(c -> StrUtil.equals("IN_PROGRESS", c.getStatus())),
                checkpoints.count(c -> StrUtil.equals("FAILED", c.getStatus()))
        );
    }

    public String getJid() {
        return vertex.getJid();
    }

    public String getName() {
        return vertex.getName();
    }

    public String getState() {
        return vertex.getState();
    }

    public Long getStartTime() {
        return vertex.getStartTime();
    }

    public Long getEndTime() {
        return vertex.getEndTime();
    }

    public Long getDuration() {
        return vertex.getDuration();
    }

    public Long getLastModification() {
        return vertex.getLastModification();
    }

    public FlinkVertex.Tasks getTasks() {
        return vertex.getTasks();
    }

    public Integer getMaxParallelism() {
        return vertex.getMaxParallelism();
    }

    public Long getNow() {
        return vertex.getNow();
    }

    public FlinkVertex.Timestamps getTimestamps() {
        return vertex.getTimestamps();
    }

    public ImmutableList<FlinkVertexChildVO> getChildren() {
        return children;
    }

    public Metrics getMetrics() {
        return metrics;
    }

    public ImmutableList<FlinkCheckpoint> getCheckpoints() {
        return checkpoints;
    }

    public CheckpointMetrics getCheckpointMetrics() {
        return checkpointMetrics;
    }

    public String getPage() {
        return page;
    }

    public static final class Metrics {
        private final Long readBytes;
        private final Long readRecords;
        private final Long writeBytes;
        private final Long writeRecords;

        public Metrics(Long readBytes, Long readRecords, Long writeBytes, Long writeRecords) {
            this.readBytes = readBytes;
            this.readRecords = readRecords;
            this.writeBytes = writeBytes;
            this.writeRecords = writeRecords;
        }

        public Long getReadBytes() {
            return readBytes;
        }

        public Long getReadRecords() {
            return readRecords;
        }

        public Long getWriteBytes() {
            return writeBytes;
        }

        public Long getWriteRecords() {
            return writeRecords;
        }
    }

    public static final class CheckpointMetrics {
        private final Integer complete;
        private final Integer inProgress;
        private final Integer failed;

        public CheckpointMetrics(Integer complete, Integer inProgress, Integer failed) {
            this.complete = complete;
            this.inProgress = inProgress;
            this.failed = failed;
        }

        public Integer getComplete() {
            return complete;
        }

        public Integer getInProgress() {
            return inProgress;
        }

        public Integer getFailed() {
            return failed;
        }
    }

    public static final class FlinkVertexChildVO {
        @JsonIgnore
        private final FlinkVertex vertex;
        private final String page;

        public FlinkVertexChildVO(FlinkVertex vertex, String page) {
            this.vertex = vertex;
            this.page = page;
        }

        public String getJid() {
            return vertex.getJid();
        }

        public String getName() {
            return vertex.getName();
        }

        public String getState() {
            return vertex.getState();
        }

        public Long getStartTime() {
            return vertex.getStartTime();
        }

        public Long getEndTime() {
            return vertex.getEndTime();
        }

        public Long getDuration() {
            return vertex.getDuration();
        }

        public Long getLastModification() {
            return vertex.getLastModification();
        }

        public FlinkVertex.Tasks getTasks() {
            return vertex.getTasks();
        }

        public Integer getMaxParallelism() {
            return vertex.getMaxParallelism();
        }

        public Long getNow() {
            return vertex.getNow();
        }

        public FlinkVertex.Timestamps getTimestamps() {
            return vertex.getTimestamps();
        }

        public ImmutableList<FlinkVertex> getChildren() {
            return vertex.getChildren();
        }

        public FlinkVertex.Metrics getMetrics() {
            return vertex.getMetrics();
        }

        public String getPage() {
            return page;
        }
    }
}
