/**
 * Yona, Project Hosting SW
 *
 * Copyright 2016 the original author or authors.
 */

package controllers.api;

import actions.NullProjectCheckAction;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import controllers.*;
import controllers.annotation.IsAllowed;
import controllers.annotation.IsCreatable;
import controllers.routes;
import models.*;
import models.enumeration.Operation;
import models.enumeration.ResourceType;
import org.joda.time.DateTime;
import play.data.Form;
import play.db.ebean.Transactional;
import play.libs.Json;
import play.mvc.Call;
import play.mvc.Result;
import play.mvc.With;
import utils.*;

import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import static play.libs.Json.toJson;

public class IssueApi extends AbstractPostingApp {

    @Transactional
    public static Result updateIssueLabel(String owner, String projectName, Long number) {
        JsonNode json = request().body().asJson();
        if(json == null) {
            return badRequest("Expecting Json data");
        }
        Project project = Project.findByOwnerAndProjectName(owner, projectName);
        Issue issue = Issue.findByNumber(project, number);
        Set<IssueLabel> labels = new HashSet<>();

        for(JsonNode node: json){
            Long labelId = Long.parseLong(node.asText());
            labels.add(IssueLabel.finder.byId(labelId));
        }

        issue.labels = labels;
        issue.save();

        ObjectNode result = Json.newObject();
        result.put("id", project.owner);
        result.put("labels", toJson(issue.labels.size()));
        return ok(result);
    }

    @IsAllowed(value = Operation.READ, resourceType = ResourceType.BOARD_POST)
    public static Result getIssue(String owner, String projectName, Long number) {
        Project project = Project.findByOwnerAndProjectName(owner, projectName);
        Issue issue = Issue.findByNumber(project, number);
        JsonNode json = ProjectApi.getResult(issue);
        return ok(json);
    }

    @Transactional
    @IsCreatable(ResourceType.ISSUE_POST)
    public static Result newIssueByJson(String owner, String projectName) {
        JsonNode json = request().body().asJson();
        if(json == null) {
            return badRequest("Expecting Json data");
        }

        Project project = Project.findByOwnerAndProjectName(owner, projectName);

        JsonNode files = json.findValue("temporaryUploadFiles");

        final Issue issue = new Issue();

        issue.createdDate = getCreatedDate(json.findValue("createdAt").asLong());
        issue.updatedDate = getCreatedDate(json.findValue("updatedAt").asLong());
        User user = findAuthor(json.findValue("author"));
        issue.setAuthor(user);
        issue.project = project;
        issue.title = json.findValue("title").asText();
        issue.body = json.findValue("body").asText();
        if(json.findValue("number") != null && json.findValue("number").asLong() > 0){
            issue.saveWithNumber(json.findValue("number").asLong());
        } else {
            issue.save();
        }
        attachUploadFilesToPost(files, issue.asResource());

        ObjectNode result = Json.newObject();
        result.put("status", 200);
        result.put("location", controllers.routes.IssueApp.issue(project.owner, project.name, issue.getNumber()).toString());
        return ok(result);
    }

    @Transactional
    @IsCreatable(ResourceType.ISSUE_COMMENT)
    public static Result newIssueCommentByJson(String ownerName, String projectName, Long number)
            throws IOException {
        JsonNode json = request().body().asJson();
        if(json == null) {
            return badRequest("Expecting Json data");
        }

        Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
        final Issue issue = Issue.findByNumber(project, number);

        if (!AccessControl.isResourceCreatable(
                UserApp.currentUser(), issue.asResource(), ResourceType.ISSUE_COMMENT)) {
            return forbidden(ErrorViews.Forbidden.render("error.forbidden", project));
        }

        User user = findAuthor(json.findValue("author"));
        String body = json.findValue("body").asText();

        final IssueComment comment = new IssueComment(issue, user, body);

        comment.createdDate = getCreatedDate(json.findValue("createdAt").asLong());
        comment.setAuthor(user);
        comment.issue = issue;
        comment.save();

        play.Logger.warn(json.findValue("temporaryUploadFiles").asText());
        attachUploadFilesToPost(json.findValue("temporaryUploadFiles"), comment.asResource());

        ObjectNode result = Json.newObject();
        result.put("status", 200);
        result.put("location", RouteUtil.getUrl(comment));

        return ok(result);
    }

    private static User findAuthor(JsonNode authorNode){
        if (authorNode != null) {
            String email = authorNode.findValue("email").asText();
            User originalAuthor = User.findByEmail(email);
            if (originalAuthor != null) {
                return originalAuthor;
            }
        }

        User user = User.findUserIfTokenExist(UserApp.currentUser());
        if (user.isAnonymous()) {
            play.Logger.error("Import error caused by unknown user import!");
        }
        return user;
    }

    private static Date getCreatedDate(long timestamp){
        if(timestamp == 0){
            return JodaDateUtil.now();
        }
        return new DateTime(timestamp).toDate();
    }
}

@@ -478,16 +478,49 @@
 ceType;%0A
+import models.enumeration.State;%0A
 import o
@@ -2981,32 +2981,77 @@
 ody%22).asText();%0A
+        issue.state = findIssueState(json);%0A%0A
         if(json.
@@ -3537,32 +3537,364 @@
 result);%0A    %7D%0A%0A
+    private static State findIssueState(JsonNode json)%7B%0A        JsonNode issueNode = json.findValue(%22state%22);%0A        State state = State.OPEN;%0A        if(issueNode != null) %7B%0A            if (%22CLOSED%22.equalsIgnoreCase(issueNode.asText())) %7B%0A                state = State.CLOSED;%0A            %7D%0A        %7D%0A        return state;%0A    %7D%0A%0A
     @Transaction

Update project import APIs - issue state