package com.ruoyi.file.object;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

public final class StateMachine
{
    public long uploadSize = 0; // 上传字节数
    public long writeSize = 0; // 写入字节数
    public long numUpload = 0; // 上传文件数
    public long numWrite = 0; // 写入文件数
    public long numError = 0; // 处理错误数
    public Date lastUploadTime; // 最近上传时间
    public Date lastWriteTime; // 最近写入时间
    public Date lastErrorTime; // 最近错误时间
    public long maxUploadSize = 0; // 最大上传字节数
    public long maxWriteSize = 0; // 最大写入字节数
    public long maxHandleDuration = 0; // 最长处理时间

    public long gcCount; // GC次数
    public Date lastGCTime; // 最近GC时间

    private final Map<String, ProjectState> projectStateMap = new LinkedHashMap<>();
    public static final StateMachine INSTANCE = new StateMachine();

    public void AddState(ProjectState state)
    {
        ProjectState projectState = projectStateMap.get(state.token);
        if(null != projectState)
            projectState.Sum(state);
        else
            projectStateMap.put(state.token, state);
        Sum(state);
    }

    private void Sum(ProjectState state)
    {
        this.uploadSize += state.uploadSize;
        this.writeSize += state.writeSize;
        this.numUpload += state.numUpload;
        this.numWrite += state.numWrite;
        this.numError += state.numError;
        if(null == this.lastUploadTime || state.lastUploadTime.after(this.lastUploadTime))
            this.lastUploadTime = state.lastUploadTime;
        if(null == this.lastWriteTime || state.lastWriteTime.after(this.lastWriteTime))
            this.lastWriteTime = state.lastWriteTime;
        if(null == this.lastErrorTime || state.lastErrorTime.after(this.lastErrorTime))
            this.lastErrorTime = state.lastErrorTime;
        if(state.maxUploadSize > this.maxUploadSize)
            this.maxUploadSize = state.maxUploadSize;
        if(state.maxWriteSize > this.maxWriteSize)
            this.maxWriteSize += state.maxWriteSize;
        if(state.maxHandleDuration > this.maxHandleDuration)
            this.maxHandleDuration += state.maxHandleDuration;
    }

    private ProjectState GetState(String token)
    {
        ProjectState state = projectStateMap.get(token);
        if(null == state)
        {
            state = new ProjectState(token);
            projectStateMap.put(token, state);
        }
        return state;
    }

    public void AddUploadSize(String token, long uploadSize)
    {
        this.uploadSize += uploadSize;
        GetState(token).AddUploadSize(uploadSize);
    }

    public void AddWriteSize(String token, long writeSize)
    {
        this.writeSize += writeSize;
        GetState(token).AddWriteSize(writeSize);
    }

    public void AddNumUpload(String token, long numUpload)
    {
        this.numUpload += numUpload;
        GetState(token).AddNumUpload(numUpload);
    }

    public void AddNumWrite(String token, long numWrite)
    {
        this.numWrite += numWrite;
        GetState(token).AddNumWrite(numWrite);
    }

    public void AddNumError(String token, long numError)
    {
        this.numError += numError;
        GetState(token).AddNumError(numError);
    }

    public void SetLastUploadTime(String token, Date lastUploadTime)
    {
        this.lastUploadTime = lastUploadTime;
        GetState(token).SetLastUploadTime(lastUploadTime);
    }

    public void SetLastWriteTime(String token, Date lastWriteTime)
    {
        this.lastWriteTime = lastWriteTime;
        GetState(token).SetLastWriteTime(lastWriteTime);
    }

    public void SetLastErrorTime(String token, Date lastErrorTime)
    {
        this.lastErrorTime = lastErrorTime;
        GetState(token).SetLastErrorTime(lastErrorTime);
    }

    public void SetMaxUploadSize(String token, long maxUploadSize)
    {
        if(maxUploadSize > this.maxUploadSize)
            this.maxUploadSize = maxUploadSize;
        GetState(token).SetMaxUploadSize(maxUploadSize);
    }

    public void SetMaxWriteSize(String token, long maxWriteSize)
    {
        if(maxWriteSize > this.maxWriteSize)
            this.maxWriteSize += maxWriteSize;
        GetState(token).SetMaxWriteSize(maxWriteSize);
    }

    public void SetMaxHandleDuration(String token, long maxHandleDuration)
    {
        if(maxHandleDuration > this.maxHandleDuration)
            this.maxHandleDuration += maxHandleDuration;
        GetState(token).SetMaxHandleDuration(maxHandleDuration);
    }

    public void IncrUploadSize(String token, long uploadSize)
    {
        this.uploadSize += uploadSize;
        GetState(token).AddUploadSize(uploadSize);
    }

    public void IncrNumUpload(String token)
    {
        this.numUpload++;
        GetState(token).AddNumUpload(1);
    }

    public void IncrNumWrite(String token)
    {
        this.numWrite++;
        GetState(token).AddNumWrite(1);
    }

    public void IncrNumError(String token)
    {
        this.numError++;
        GetState(token).AddNumError(1);
    }

    public void GC()
    {
        System.gc();
        gcCount++;
        lastGCTime = new Date();
    }

    private StateMachine() {}
}
