/**
 * Yobi, Project Hosting SW
 *
 * Copyright 2012 NAVER Corp.
 * http://yobi.io
 *
 * @Author Yi EungJun
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package controllers;

import controllers.annotation.IsAllowed;
import controllers.annotation.IsCreatable;
import models.IssueLabel;
import models.Project;
import models.enumeration.Operation;
import models.enumeration.ResourceType;
import play.data.DynamicForm;
import play.data.Form;
import play.db.ebean.Transactional;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Result;
import utils.ErrorViews;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static play.data.Form.form;
import static play.libs.Json.toJson;

public class IssueLabelApp extends Controller {
    /**
     * Responds to a request for issue labels of the specified project.
     *
     * This method is used when put a label on an issue and list labels in
     * issue list page.
     *
     * Retrieves a project corresponding to {@code ownerName} and {@code
     * projectName}, and returns its list of all issue labels in {@code
     * application/json}. Each label has three fields: {@link IssueLabel#id},
     * {@link IssueLabel#category}, {@link IssueLabel#color}, and {@link
     * IssueLabel#name}.
     *
     * Returns 403 Forbidden if the user has no permission to access to the
     * project.
     *
     * Returns 406 Not Acceptable if the client cannot accept
     * {@code application/json}. Success response can only be returned when the
     * content type of the body is {@code application/json}.
     *
     * @param ownerName    the name of a project owner
     * @param projectName  the name of a project
     * @return the response to the request for issue labels
     */
    @IsAllowed(Operation.READ)
    public static Result labels(String ownerName, String projectName) {
        if (!request().accepts("application/json")) {
            return status(Http.Status.NOT_ACCEPTABLE);
        }

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

        List<Map<String, String>> labels = new ArrayList<>();
        for (IssueLabel label : IssueLabel.findByProject(project)) {
            Map<String, String> labelPropertyMap = new HashMap<>();
            labelPropertyMap.put("id", "" + label.id);
            labelPropertyMap.put("category", label.category);
            labelPropertyMap.put("color", label.color);
            labelPropertyMap.put("name", label.name);
            labels.add(labelPropertyMap);
        }

        response().setHeader("Content-Type", "application/json");
        return ok(toJson(labels));
    }

    /**
     * Responds to a request to add an issue label for the specified project.
     *
     * This method is used when a user tries to add a issue label in issue list,
     * editing issue or new issue page.
     *
     * Adds an issue label created with values taken from
     * {@link Form#bindFromRequest(java.util.Map, String...)} in the project
     * specified by the {@code ownerName} and {@code projectName}. But if there
     * has already been the same issue label in category, name and color, then
     * this method returns an empty 204 No Content response.
     *
     * When a new label is added, this method encodes the label's fields:
     * {@link IssueLabel#id}, {@link IssueLabel#name}, {@link IssueLabel#color},
     * and {@link IssueLabel#category} into {@code application/json}, and
     * includes them in the body of the 201 Created response. But if the client
     * cannot accept {@code application/json}, it returns the 201 Created with
     * no response body.
     *
     * Returns 403 Forbidden, if the user has no permission to add a new label
     * in the project.
     *
     * @param ownerName    the name of a project owner
     * @param projectName  the name of a project
     * @return             the response to the request to add a new issue label
     */
    @Transactional
    @IsCreatable(ResourceType.ISSUE_LABEL)
    public static Result newLabel(String ownerName, String projectName) {
        Form<IssueLabel> labelForm = new Form<>(IssueLabel.class).bindFromRequest();
        Project project = Project.findByOwnerAndProjectName(ownerName, projectName);

        IssueLabel label = labelForm.get();
        label.project = project;

        if (label.exists()) {
            return noContent();
        } else {
            label.save();

            if (!request().accepts("application/json")) {
                return created();
            }

            response().setHeader("Content-Type", "application/json");

            Map<String, String> labelPropertyMap = new HashMap<>();
            labelPropertyMap.put("id", "" + label.id);
            labelPropertyMap.put("name", label.name);
            labelPropertyMap.put("color", label.color);
            labelPropertyMap.put("category", label.category);

            return created(toJson(labelPropertyMap));
        }
    }

    /**
     * Responds to a request to delete the specified issue label.
     *
     * This method is used when a user click a button to delete a issue label
     * in issue list, editing issue or new issue page.
     *
     * Deletes an issue label corresponding to the given {@code id}.
     *
     * - Returns {@code 200 OK} if the issue label is deleted succesfully.
     * - Returns {@code 403 Forbidden} if the user has no permission to delete
     *   the issue label.
     * - Returns {@code 404 Not Found} if no issue label is found.
     *
     * The request must have a {@code _method} parameter and the parameter
     * value must be case-insensitive "delete"; otherwise, returns 400 Bad
     * Request. We use this trick because an HTML Form does not support the
     * DELETE method.
     *
     * @param ownerName    Don't use.
     * @param projectName  Don't use.
     * @param id           the id of the label to be deleted
     * @return             the response to the request to delete an issue label
     */
    @Transactional
    @IsAllowed(value = Operation.DELETE, resourceType = ResourceType.ISSUE_LABEL)
    public static Result delete(String ownerName, String projectName, Long id) {
        // _method must be 'delete'
        DynamicForm bindedForm = form().bindFromRequest();
        if (!bindedForm.get("_method").toLowerCase()
                .equals("delete")) {
            return badRequest(ErrorViews.BadRequest.render("_method must be 'delete'."));
        }

        IssueLabel label = IssueLabel.finder.byId(id);
        label.delete();
        return ok();
    }

    /**
     * Responds to a request for the CSS styles of all issue labels in the
     * specified project.
     *
     * This method is used when CSS styles of issue labels are required in any
     * page which uses issue label.
     *
     * @param ownerName    the name of a project owner
     * @param projectName  the name of a project
     * @return the response to the request for the css styles in text/css.
     */
    @IsAllowed(Operation.READ)
    public static Result labelStyles(String ownerName, String projectName) {
        Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
        List<IssueLabel> labels = IssueLabel.findByProject(project);

        String eTag = "\"" + labels.hashCode() + "\"";
        String ifNoneMatchValue = request().getHeader("If-None-Match");

        if(ifNoneMatchValue != null && ifNoneMatchValue.equals(eTag)) {
            response().setHeader("ETag", eTag);
            return status(NOT_MODIFIED);
        }

        response().setHeader("ETag", eTag);

        return ok(views.html.common.issueLabelColor.render(labels)).as("text/css");
    }
}

@@ -1686,13 +1686,12 @@
 has 
-three
+four
  fie

Fix a typo