package com.atlassian.bitbucket.rest.repository;

import com.atlassian.bitbucket.repository.*;
import com.atlassian.bitbucket.rest.RestMapEntity;
import com.atlassian.bitbucket.rest.annotation.JsonSurrogate;
import org.codehaus.jackson.map.annotate.JsonSerialize;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.function.Function;

@JsonSerialize
@JsonSurrogate(MinimalRef.class)
public class RestMinimalRef extends RestMapEntity implements MinimalRef {

    public static final Function<MinimalRef, RestMinimalRef> REST_TRANSFORM = ref -> {
        if (ref == null) {
            return null;
        }

        if (ref instanceof Branch) {
            return new RestBranch((Branch) ref);
        }
        if (ref instanceof Tag) {
            return new RestTag((Tag) ref);
        }
        return ref instanceof Ref ? new RestRef((Ref) ref) : new RestMinimalRef(ref);
    };

    protected static final String DISPLAY_ID = "displayId";
    protected static final String ID = "id";
    protected static final String TYPE = "type";

    private RestMinimalRef(Map<String, Object> map) {
        super(map);
    }

    public RestMinimalRef() {
    }

    public RestMinimalRef(MinimalRef ref) {
        this(ref.getId(), ref.getDisplayId(), ref.getType());
    }

    protected RestMinimalRef(String id, String displayId, RefType type) {
        put(ID, id);
        put(DISPLAY_ID, displayId);
        put(TYPE, type.toString());
    }

    @Nonnull
    @Override
    public String getDisplayId() {
        return getStringProperty(DISPLAY_ID);
    }

    @Nonnull
    public String getId() {
        return getStringProperty(ID);
    }

    @Nonnull
    @Override
    public RefType getType() {
        return getEnumProperty(TYPE, StandardRefType.class, null);
    }

    @Nullable
    @SuppressWarnings("unchecked")
    public static RestMinimalRef valueOf(@Nullable Object value) {
        if (value instanceof RestMinimalRef) {
            return (RestMinimalRef) value;
        } else if (value instanceof Map) {
            return new RestMinimalRef((Map) value);
        }
        return null;
    }
}
