package com.atlassian.stash.internal.web.admin;

import com.atlassian.crowd.embedded.api.Group;
import com.atlassian.crowd.exception.runtime.CrowdRuntimeException;
import com.atlassian.bitbucket.IntegrityException;
import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.stash.internal.web.soy.StashSoyResponseBuilder;
import com.atlassian.stash.internal.web.util.ControllerSupport;
import com.atlassian.bitbucket.nav.NavBuilder;
import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.permission.PermissionService;
import com.atlassian.bitbucket.user.UserAdminService;
import com.atlassian.bitbucket.validation.annotation.RequiredString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.Valid;

import static org.apache.commons.lang3.StringUtils.trim;

@Controller
@RequestMapping(value = "/admin/groups", params = "create")
public class GroupCreateController extends ControllerSupport {

    private static final String FORM_VIEW = "bitbucket.internal.admin.groups.create";

    private final UserAdminService adminService;
    private final PermissionService permissionService;
    private final NavBuilder navBuilder;

    @Autowired
    public GroupCreateController(I18nService i18nService, UserAdminService adminService,
                                 NavBuilder navBuilder, PermissionService permissionService) {
        super(i18nService);

        this.adminService = adminService;
        this.navBuilder = navBuilder;
        this.permissionService = permissionService;
    }

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView showForm() {
        if (permissionService.hasGlobalPermission(Permission.ADMIN)) {
            return new StashSoyResponseBuilder(FORM_VIEW)
                    .build();
        } else {
            throw new AccessDeniedException(i18nService.getMessage("bitbucket.web.group.create.accessdenied"));
        }
    }

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView createGroup(@Valid GroupForm groupForm, Errors errors) {
        final String name = trim(groupForm.getName());
        if (!errors.hasErrors()) {
            try {
                adminService.createGroup(name);
                return new ModelAndView("redirect:" + navBuilder.admin().groups().view(name).buildRelNoContext());
            } catch (IntegrityException e) {
                errors.rejectValue("name", e.getMessageKey(), e.getLocalizedMessage());
            } catch (CrowdRuntimeException e) {
                return handleCrowdException(e, groupForm);
            }
        }
        return showForm(groupForm).putValidationErrors(errors).build();
    }

    private ModelAndView handleCrowdException(CrowdRuntimeException e, GroupForm groupForm) {
        String name = groupForm.getName();
        log.error(String.format("The group %s could not be created", name), e);
        String error = i18nService.getMessage("bitbucket.web.group.create.crowdError", name);
        return showForm(groupForm).putFormErrors(error).build();
    }

    private StashSoyResponseBuilder showForm(GroupForm groupForm) {
        return new StashSoyResponseBuilder(FORM_VIEW).put("groupForm", groupForm);
    }

    @SuppressWarnings("unused") //Fully used by SpringMVC
    public static class GroupForm implements Group {
        
        private String name;

        @Override
        @RequiredString(size = 255)
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public int compareTo(Group o) {
            return this.getName().compareTo(o.getName());
        }
    }
}
