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

import com.atlassian.stash.internal.web.util.xsrf.XsrfTokenGenerator;
import com.atlassian.stash.internal.web.util.xsrf.XsrfTokenInterceptor;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Tells the user that their POST failed due to an expired/missing token, and allows them to submit the request again.
 */
@Controller
@RequestMapping("/xsrfNotification")
public class XsrfNotificationController {

    private final XsrfTokenGenerator xsrfTokenGenerator;

    @Autowired
    public XsrfNotificationController(XsrfTokenGenerator xsrfTokenGenerator) {
        this.xsrfTokenGenerator = xsrfTokenGenerator;
    }

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView notify(HttpServletRequest request) {
        Map<String, String[]> paramMap = new HashMap<String, String[]>(request.getParameterMap());
        // this is the old invalid token -- the new token will be placed in the form by the view
        paramMap.remove(xsrfTokenGenerator.getXsrfTokenName());

        return new ModelAndView(
                "bitbucket.internal.auth.xsrfNotification",
                "xsrfModel",
                new XsrfNotificationModel((String) request.getAttribute(XsrfTokenInterceptor.XSRF_ORIGINAL_URL), paramMap)
        );
    }

    public static class XsrfNotificationModel {
        private final String action;
        private final List<FormParameter> formValues;

        private XsrfNotificationModel(String action, Map<String, String[]> formValues) {
            this.action = action;
            this.formValues = Lists.newArrayList();
            for (Map.Entry<String, String[]> entry : formValues.entrySet()) {
                for (String s : entry.getValue()) {
                    this.formValues.add(new FormParameter(entry.getKey(), s));
                }
            }
        }

        public String getAction() {
            return action;
        }

        public List<FormParameter> getFormValues() {
            return formValues;
        }
    }

    public static class FormParameter {

        private final String name;
        private final String value;

        public FormParameter(String name, String value) {
            this.name = name;
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public String getValue() {
            return value;
        }
    }

}
