package tc.oc.pgm.goals;

import java.util.logging.Logger;
import javax.annotation.Nullable;

import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import tc.oc.api.docs.AbstractModel;
import tc.oc.api.docs.virtual.MatchDoc;
import tc.oc.commons.core.logging.ClassLogger;
import tc.oc.pgm.match.Competitor;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.match.Party;
import tc.oc.pgm.map.ProtoVersions;
import tc.oc.pgm.score.ScoreMatchModule;

/**
 * Basic {@link Goal} implementation with fields for the definition and match
 */
public abstract class SimpleGoal<T extends GoalDefinition> implements Goal<T> {

    public static final ChatColor COLOR_INCOMPLETE = ChatColor.RED;
    public static final ChatColor COLOR_COMPLETE = ChatColor.GREEN;

    public static final String SYMBOL_INCOMPLETE = "\u2715";        // ✕
    public static final String SYMBOL_COMPLETE = "\u2714";          // ✔

    protected final Logger logger;
    protected final T definition;
    protected final Match match;

    public SimpleGoal(T definition, Match match) {
        this.logger = ClassLogger.get(match.getLogger(), getClass());
        this.definition = definition;
        this.match = match;
    }

    @Override
    public String slug() {
        return match.featureDefinitions().slug(getDefinition());
    }

    @Override
    public Match getMatch() {
        return this.match;
    }

    @Override
    public T getDefinition() {
        return this.definition;
    }

    @Override
    public String getName() {
        return this.definition.getName();
    }

    @Override
    public String getColoredName() {
        return this.definition.getColoredName();
    }

    @Override
    public BaseComponent getComponentName() {
        return this.definition.getComponentName();
    }

    @Override
    public Color getColor() {
        return getDyeColor().getColor();
    }

    @Override
    public DyeColor getDyeColor() {
        return DyeColor.WHITE;
    }

    @Override
    public boolean isVisible() {
        return this.definition.isVisible();
    }

    @Override
    public boolean isRequired() {
        Boolean required = getDefinition().isRequired();
        if(required != null) {
            return required;
        } else if(getMatch().getModuleContext().getProto().isNoOlderThan(ProtoVersions.GOAL_REQUIRED_OPTION)) {
            return true;
        } else {
            // Legacy behavior is to require no goals if score module is loaded
            return !getMatch().hasMatchModule(ScoreMatchModule.class);
        }
    }

    public ChatColor renderSidebarStatusColor(@Nullable Competitor competitor, Party viewer) {
        return isCompleted(competitor) ? COLOR_COMPLETE : COLOR_INCOMPLETE;
    }

    public String renderSidebarStatusText(@Nullable Competitor competitor, Party viewer) {
        return isCompleted(competitor) ? SYMBOL_COMPLETE : SYMBOL_INCOMPLETE;
    }

    public ChatColor renderSidebarLabelColor(@Nullable Competitor competitor, Party viewer) {
        return ChatColor.WHITE;
    }

    public String renderSidebarLabelText(@Nullable Competitor competitor, Party viewer) {
        return getName();
    }

    public class Document extends AbstractModel implements MatchDoc.Goal {
        @Override
        public String _id() {
            return slug();
        }

        @Override
        public String type() {
            return getDefinition().getFeatureName();
        }

        @Override
        public String name() {
            return getName();
        }
    }
}
