package com.atlassian.bitbucket.rest.content;

import com.atlassian.bitbucket.content.Diff;
import com.atlassian.bitbucket.property.PropertyMap;
import com.atlassian.bitbucket.rest.RestMapEntity;
import com.atlassian.bitbucket.rest.annotation.JsonSurrogate;
import com.atlassian.bitbucket.rest.comment.RestComment;
import com.atlassian.bitbucket.rest.property.RestPropertySupport;
import com.atlassian.bitbucket.rest.util.RestDocUtils;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.codehaus.jackson.map.annotate.JsonSerialize;

import java.util.Collections;
import java.util.function.Function;

@JsonSerialize
@JsonSurrogate(Diff.class)
public class RestDiff extends RestPropertySupport {

    public static final Function<Diff, RestDiff> REST_TRANSFORM = RestDiff::new;

    @SuppressWarnings("unused") //Required for Jersey
    public RestDiff() {
    }

    public RestDiff(Diff diff) {
        this(RestPath.fromPath(diff.getSource()), RestPath.fromPath(diff.getDestination()), diff.isBinary(),
                (diff.isBinary() ? null : transform(diff.getHunks(), RestDiffHunk.REST_TRANSFORM)), null,
                diff.isTruncated(), diff.getProperties());
    }

    // Required for REST documentation
    private RestDiff(RestPath source, RestPath destination, boolean isBinary, Iterable<RestDiffHunk> hunks,
                     Iterable<RestComment> lineComments, boolean isTruncated, PropertyMap properties) {
        put("source", source);
        put("destination", destination);
        if (isBinary) {
            put("binary", true);
        } else {
            put("hunks", hunks);
            putIfNotEmpty("lineComments", lineComments);
            putIfNotNull("truncated", isTruncated);
            putProperties(properties);
        }
    }

    // REST Documentation Examples

    public static final RestDiff EXAMPLE = enrichTopLevel(new RestDiff(RestPath.EXAMPLE, RestPath.EXAMPLE, false,
            Lists.newArrayList(RestDiffHunk.HUNKY_EXAMPLE), null, false, null));
    public static final RestDiff EXAMPLE_COMMENT = enrichTopLevel(new RestDiff(RestPath.EXAMPLE, RestPath.EXAMPLE,
            false,
            Lists.newArrayList(RestDiffHunk.HUNKY_EXAMPLE_COMMENTED),
            Lists.newArrayList(RestComment.RESPONSE_EXAMPLE_NO_REPLY), false, null));

    public static final RestMapEntity PAGE_EXAMPLE = enrichTopLevel(RestDocUtils.wrap(
            Collections.singletonList(RestDiff.EXAMPLE), "diffs"));

    public static final RestMapEntity PAGE_WITH_COMMENTS_EXAMPLE = enrichTopLevel(RestDocUtils.wrap(
            Collections.singletonList(RestDiff.EXAMPLE_COMMENT), "diffs"));

    private static <T extends RestMapEntity> T enrichTopLevel(T entity) {
        return RestDocUtils.decorate(entity, ImmutableMap.of(
                "truncated", "true",
                "contextLines", "10",
                "fromHash", "a0f224fd7bd5f28ea5a752d41b9c9f6372fc6d9e",
                "toHash", "dc93f22caadcde35daf5cc2cd65d2738c87e31ca",
                "whiteSpace", "SHOW"));
    }
}
