package com.atlassian.bitbucket.mesh.repair;

import com.atlassian.bitbucket.mesh.git.ref.ProposedRefUpdate;
import com.atlassian.bitbucket.mesh.git.ref.Ref;
import com.atlassian.bitbucket.mesh.util.ShaUtils;

import javax.annotation.Nonnull;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;

/**
 * {@link Differ} specialization for comparing sequences of {@link Ref}s that translates detected differences into
 * {@link ProposedRefUpdate}.
 */
class RefDiffer extends Differ<Ref> {

    private static final Comparator<Ref> REF_COMPARATOR = Comparator.comparing(Ref::getId);
    private static final BiPredicate<Ref, Ref> REF_EQUALITY =
            (ref1, ref2) -> ShaUtils.hashesMatch(ref1.getObjectId(), ref2.getObjectId());

    RefDiffer(@Nonnull Consumer<ProposedRefUpdate> callback) {
        super(REF_COMPARATOR, REF_EQUALITY, (fromRef, toRef) -> {
            if (toRef == null) {
                callback.accept(ProposedRefUpdate.toDelete(fromRef.getId(), fromRef.getObjectId()));
            } else if (fromRef == null) {
                callback.accept(ProposedRefUpdate.toAdd(toRef.getId(), toRef.getObjectId()));
            } else {
                callback.accept(ProposedRefUpdate.of(toRef.getId(), fromRef.getObjectId(), toRef.getObjectId()));
            }
        });
    }
}
