// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.codec.validation;

import java.util.logging.Level;
import com.hypixel.hytale.codec.exception.CodecValidationException;
import javax.annotation.Nonnull;
import com.hypixel.hytale.logger.HytaleLogger;
import java.util.Iterator;
import java.util.Collection;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import javax.annotation.Nullable;
import java.util.List;
import com.hypixel.hytale.codec.ExtraInfo;

public class ValidationResults
{
    protected final ExtraInfo extraInfo;
    @Nullable
    protected List<ValidatorResultsHolder> validatorExceptions;
    @Nullable
    protected List<ValidationResult> results;
    
    public ValidationResults(final ExtraInfo extraInfo) {
        this.extraInfo = extraInfo;
    }
    
    public ExtraInfo getExtraInfo() {
        return this.extraInfo;
    }
    
    public void fail(final String reason) {
        this.add(ValidationResult.fail(reason));
    }
    
    public void warn(final String reason) {
        this.add(ValidationResult.warn(reason));
    }
    
    public void add(final ValidationResult result) {
        if (this.results == null) {
            this.results = new ObjectArrayList<ValidationResult>();
        }
        this.results.add(result);
    }
    
    public void _processValidationResults() {
        if (this.results == null || this.results.isEmpty()) {
            return;
        }
        for (final ValidationResult validationResult : this.results) {
            final Result result = validationResult.result;
            if (result == Result.WARNING || result == Result.FAIL) {
                if (this.validatorExceptions == null) {
                    this.validatorExceptions = new ObjectArrayList<ValidatorResultsHolder>();
                }
                this.validatorExceptions.add(new ValidatorResultsHolder(this.extraInfo.peekKey(), this.extraInfo.peekLine(), this.extraInfo.peekColumn(), new ObjectArrayList<ValidationResult>(this.results)));
                break;
            }
        }
        this.results.clear();
    }
    
    public void logOrThrowValidatorExceptions(@Nonnull final HytaleLogger logger) {
        this.logOrThrowValidatorExceptions(logger, "Failed to validate asset!\n");
    }
    
    public void logOrThrowValidatorExceptions(@Nonnull final HytaleLogger logger, @Nonnull final String msg) {
        if (this.validatorExceptions == null || this.validatorExceptions.isEmpty()) {
            return;
        }
        final StringBuilder sb = new StringBuilder(msg);
        this.extraInfo.appendDetailsTo(sb);
        boolean failed = false;
        for (final ValidatorResultsHolder holder : this.validatorExceptions) {
            if (holder.key != null && !holder.key.isEmpty()) {
                sb.append("Key: ").append(holder.key).append("\n");
            }
            sb.append("Results:\n");
            for (final ValidationResult result : holder.results) {
                failed |= result.appendResult(sb);
            }
        }
        if (failed) {
            throw new CodecValidationException(sb.toString());
        }
        logger.at(Level.WARNING).log(sb.toString());
        this.validatorExceptions.clear();
    }
    
    public boolean hasFailed() {
        if (this.results == null) {
            return false;
        }
        for (final ValidationResult res : this.results) {
            if (res.result() == Result.FAIL) {
                return true;
            }
        }
        return false;
    }
    
    @Nullable
    public List<ValidationResult> getResults() {
        if (this.results == null) {
            return null;
        }
        return this.results;
    }
    
    public void setResults(@Nullable final List<ValidationResult> results) {
        this.results = results;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "ValidationResults{results=" + String.valueOf(this.results);
    }
    
    public enum Result
    {
        SUCCESS, 
        WARNING, 
        FAIL;
    }
    
    record ValidationResult(Result result, String reason) {
        public boolean appendResult(@Nonnull final StringBuilder sb) {
            sb.append("\t").append(this.result).append(": ").append(this.reason).append("\n");
            return this.result == Result.FAIL;
        }
        
        @Nonnull
        public static ValidationResult fail(final String reason) {
            return new ValidationResult(Result.FAIL, reason);
        }
        
        @Nonnull
        public static ValidationResult warn(final String reason) {
            return new ValidationResult(Result.WARNING, reason);
        }
    }
    
    record ValidatorResultsHolder(String key, int line, int column, List<ValidationResult> results) {}
}
